用JavaScript构建类似于DSL的DSL

问题描述 投票:0回答:1

我想更多地探索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是我要模仿的,但是我不确定从哪里开始或去弄清楚如何进行DSL创建,就像在Ruby中一样。

我的Ruby DSL完整示例:https://github.com/FilBot3/phil_dsl

javascript dsl
1个回答
0
投票

在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定义为箭头函数I 保证,所以其中的this将始终引用MyDsl

然后我可以像这样使用DSL:

MyDsl.print_stuff("foo", function() {
  this.print_stuff("bar");
});

请注意,我们不能在此处使用错误函数,因为这样会忽略.apply(this)

© www.soinside.com 2019 - 2024. All rights reserved.