Я пытаюсь построить привязываемый JavaScript API. (Я запускаю это в последней версии V8 с включенными итераторами и генераторами.) В приведенном ниже примере setState
является цепным. Он также позволяет вам вызывать его без необходимости явно создавать новый экземпляр Builder
. Вспомогательная функция chain()
обрабатывает это и автоматически возвращает этот экземпляр, поэтому setState
не должен беспокоиться об этом. (Первоклассные функции для победы!)Эквивалент функции.prototype.apply для генератора ES6
В дополнение к методам, связанным с цепью, я хочу использовать некоторые «завершающие» методы. Кикер состоит в том, что эти «терминаторы» являются генераторами. Генераторы приводят к внутреннему состоянию экземпляра 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;
Который возвращает
[
"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"
]
Да, вы правы, например: (функция *() {}) InstanceOf функции; // true var gen = function *() { yield this.random(); } gen.apply (Math, gen) .next(). Value; Я должен делать что-то еще не так в моем коде. Позволь мне еще раз нанести удар. –
Обратите внимание, что моя функция 'delegate' больше не возвращает функцию-генератор * - возвращает нормальную' функцию' (которая возвращает генератор). – Bergi
Справа. Я скорректировал свое решение ниже, чтобы вернуть генератор, который дает результат применения генератора. –