我想更多地探索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是我要模仿的,但是我不确定从哪里开始或去弄清楚如何进行DSL创建,就像在Ruby中一样。
我的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
定义为箭头函数I 保证,所以其中的this
将始终引用MyDsl
。
然后我可以像这样使用DSL:
MyDsl.print_stuff("foo", function() {
this.print_stuff("bar");
});
请注意,我们不能在此处使用错误函数,因为这样会忽略.apply(this)
。