我想更多地研究JavaScript,想看看我是否可以创建一种域特定语言,类似于我可以使用instance_eval
和block_given?
在Ruby中制作的语言。我大多不知道要搜索什么术语,当我搜索DSL时,我通常会得到一些我不熟悉的元内容。我最初在Ruby搜索中非常幸运,并找到了一个帮助我的好博客。我在 Ruby 中的例子是:
# frozen_string_literal: true
require 'phil_dsl/version'
module PhilDsl
class Error < StandardError; end
# The DSL Class.
class Pipeline
def initialize(&block)
if block_given? # rubocop:disable Style/GuardClause
if block.arity == 1
yield self
else
instance_eval(&block)
end
end
end
def pipeline(&block)
if block_given? # rubocop:disable Style/GuardClause
if block.arity == 1
yield self
else
instance_eval(&block)
end
end
end
def print_stuff(name = 'bob', &block)
puts name.to_s
if block_given? # rubocop:disable Style/GuardClause
if block.arity == 1
yield self
else
instance_eval(&block)
end
end
end
end
end
然后是DSL的实际使用情况,一旦安装完毕
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'phil_dsl'
PhilDsl::Pipeline.new.pipeline do
print_stuff('hello') do
print_stuff
end
end
查看MochaJS是我想模仿的,但是我不确定从哪里开始或弄清楚如何进行类似于我在Ruby中可以做的DSL创建。
我的Ruby DSL完整示例:https://github.com/FilBot3/phil_dsl
它在JS中没有那么漂亮,因为你总是需要this
关键字,但DSL的核心部分是instance_exec
功能,这在JS中使用bind
,apply
或箭头函数非常容易做到。
我将使用 IIFE 构建一个新作用域,而不是使用类(不支持箭头函数(:
MyDsl = (function(){
return this;
}).apply({});
然后,我将添加一个单函数DSL:
MyDsl = (function(){
this.print_stuff = (arg, callback) => {
console.log(arg);
callback && callback.apply(this);
};
return this;
}).apply({});
由于我将print_stuff
定义为箭头函数,因此我保证在其内部,this
将始终引用MyDsl
。
然后我可以像这样使用 DSL:
MyDsl.print_stuff("foo", function() {
this.print_stuff("bar");
});
请注意,我们不能在这里使用 error 函数,因为这样.apply(this)
将被忽略。