【发布时间】:2015-02-09 06:04:04
【问题描述】:
我正在尝试构建一个可链接的 JavaScript API。 (我在启用了迭代器和生成器的最新版本的 V8 中运行它。)在下面的示例中,setState 是可链接的。它还允许您调用它而无需显式创建新的Builder 实例。 chain() 帮助函数处理并自动返回该实例,因此setState 不必担心它。 (一流的功能!)
除了可链接的方法之外,我还想要一些“终止”方法。更重要的是这些“终结者”是生成器。生成器产生Builder 实例的内部状态。问题是我无法找出与 f.apply(that, arguments) 等效的生成器。我希望能够在运行时调用生成器并设置其this 上下文,就像您可以使用Function.prototype.apply 和Function.prototype.call 一样。
用Yuck! 评论的解决方法是在Builder.prototype 上公开委托的和原始生成器,从委托中调用原始生成器。有什么方法可以实现类似chain 方法的等效包装,而不必在Builder.prototype 上公开_generate 方法?
function Builder() { this.initialState = 'initialState'; };
Builder.prototype.setState = chain(function(k, v) { this[k] = v; });
Builder.prototype.generate = delegate(generate, '_generate'); // Yuck!
Builder.prototype._generate = generate;
function chain(f) {
return function() {
var that = (this instanceof Builder) ? this : new Builder();
f.apply(that, arguments); // Pass through arguments
return that;
}
}
function delegate(gen, _gen) {
return function*() {
var that = (this instanceof Builder) ? this : new Builder();
that.setState('delegated', true);
yield *that[_gen](); // Yuck!
}
}
function *generate(opts) {
var i = 0;
for(var i = 0; i < 10; i++) {
yield [Object.keys(this), opts, i].join(',');
}
}
// Set up a namespace
var ns = {};
ns.setState = Builder.prototype.setState;
ns.generate = Builder.prototype.generate;
var itr = ns
// .setState('a', 'A')
// .setState('b', 'B')
// .setState('c', 'C')
.generate('options');
var out = [];
for(var value of itr) { out.push(value); }
out;
返回
[
"initialState,delegated,,0",
"initialState,delegated,,1",
"initialState,delegated,,2",
"initialState,delegated,,3",
"initialState,delegated,,4",
"initialState,delegated,,5",
"initialState,delegated,,6",
"initialState,delegated,,7",
"initialState,delegated,,8",
"initialState,delegated,,9"
]
【问题讨论】:
标签: javascript generator v8 ecmascript-6