5

次のようなジェネレーター関数があるとします。

var g = function*() {
  yield 1;
  yield 2;
  yield 3;
};

var gen = g();

gそれがジェネレーター関数であるかgen、イテレーターであるかをプログラムでどのように判断できますか?

これは1つの可能性のようです:

g.constructor.name === 'GeneratorFunction'

より良い方法はありますか?

更新:私はエリックの答えに似たアプローチをとることになりましたが、最初にターゲットプラットフォームでジェネレーターがサポートされているかどうかを最初に判断するために使用しました。実装は次のとおりです。eval

var GeneratorConstructor = (function() {
  try {
    var generator;
    return eval('generator = function*() { yield 1; };').constructor;

  } catch (e) {
    // If the above throws a SyntaxError, that means generators aren't
    // supported on the current platform, which means isGenerator should
    // always return false. So we'll return an anonymous function here, so
    // that instanceof checks will always return false.
    return function() {};
  }
}());

/**
 * Checks whether a function is an ES6 Harmony generator.
 *
 * @private
 * @param {Function} fn
 * @returns {boolean}
 */
function isGenerator(fn) {
  return fn instanceof GeneratorConstructor;
}
4

3 に答える 3

5

ソリューションを他のソリューションと組み合わせると、 global の必要がなくなりますGeneratorFunction

g instanceof (function*() {}).constructor
于 2014-02-04T17:50:04.580 に答える
1

何かがジェネレーターかどうかを判断するには:

const g = (function*() {yield 1;});
const GeneratorFunctionPrototype = Object.getPrototypeOf(g);

function isGenerator(thing) {
  return typeof thing === 'object' && thing.constructor === GeneratorFunctionPrototype;
}

元の質問では、これは真に答えisGenerator(gen)ます。Whilegはジェネレータ関数です。ジェネレーター関数を呼び出すと、ジェネレーターが生成されます。

しかし、ほとんどの場合、それがiteratorであるかどうかを尋ねる方が重要です:

function isIterator(thing) {
  // If thing has a Symbol.iterator
  return typeof thing === 'object' && thing[Symbol.iterator];
}

使用法:

function *Pseq(list, repeats=1) {
  for (let i = 0; i < repeats; i++) {
    for (let value of list) {
      if (isIterator(value)) {
        yield *value;
      } else {
        yield value;        
      }
    }    
  }
}

let q = Pseq([1, 2, 3, Pseq([10, 20, 30], 2), 4], 2);

for (let v of q) {
  console.log(v);
}

1 2 3 10 20 30 10 20 30 4 1 2 3 4

これはシーケンスを反復しています。そのシーケンスにイテレータが埋め込まれている場合は、シーケンスを続行する前に、yield 委譲を使用してそれを反復処理します。ジェネレーターは、生成できる便利なイテレーターを生成する唯一のものではありません。

于 2016-11-11T11:23:37.517 に答える