Jus*_*eig 6 javascript v8 generator ecmascript-6
我正在尝试构建一个可链接的JavaScript API.(我在最新版本的V8中运行它,启用了迭代器和生成器.)在下面的示例中,setState是可链接的.它还允许您调用它而无需显式创建新Builder实例.该chain()辅助函数处理该自动返回该实例所以setState不必担心.(胜利的一流功能!)
除了可链接的方法,我想要一些"终止"方法.踢球者是这些"终结者"是发电机.生成器生成Builder实例的内部状态.问题是我无法弄清楚f.apply(that, arguments)发电机的等价物.我希望能够this在运行时调用生成器并设置其上下文,就像您可以使用Function.prototype.apply和Function.prototype.call.
解决方法Yuck!是在委托上公开委托和原始生成器Builder.prototype,从委托调用原始生成器.有没有办法像chain方法一样实现等效包装而不必在_generate方法上公开方法Builder.prototype?
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;
Run Code Online (Sandbox Code Playgroud)
哪个回报
[
"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"
]
Run Code Online (Sandbox Code Playgroud)
关键yield *gen.apply(that, arguments)在于匿名生成器包装器。
function Builder() { this.initialState = 'initialState'; };
Builder.prototype.setState = chain(function(k, v) { this[k] = v; });
Builder.prototype.generate = delegate(generate);
// Reuses or creates a Builder instance and makes it `this` for calling `f`.
// Returns the Builder instance.
function chain(f) {
return function() {
var that = (this instanceof Builder) ? this : new Builder();
f.apply(that, arguments); // Pass through arguments
return that;
}
}
// Similar to `chain()` to create a Builder instance if it doesn't exist.
// Generators are terminal, though, so this returns the FunctionGenerator.
function delegate(gen) {
return function*() {
var that = (this instanceof Builder) ? this : new Builder();
that.setState('delegated', true);
yield *gen.apply(that, arguments);
}
}
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;
Run Code Online (Sandbox Code Playgroud)