在JavaScript中构建类似于Ruby DSL的DSL



我想更多地研究JavaScript,想看看我是否可以创建一种域特定语言,类似于我可以使用instance_evalblock_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中使用bindapply或箭头函数非常容易做到。

我将使用 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)将被忽略。

最新更新