检查函数是否是生成器

IT技术 javascript generator yield ecmascript-6
2021-03-14 07:48:37

我在 Nodejs v0.11.2 中使用了生成器,我想知道如何检查我的函数的参数是生成器函数。

我找到了这种方式,typeof f === 'function' && Object.getPrototypeOf(f) !== Object.getPrototypeOf(Function)但我不确定这是否是好的(并在未来工作)方式。

您对这个问题有什么看法?

6个回答

在最新版本的 nodejs(我用 v0.11.12 验证过)中,您可以检查构造函数名称是否等于GeneratorFunction. 我不知道这是什么版本,但它有效。

function isGenerator(fn) {
    return fn.constructor.name === 'GeneratorFunction';
}
“您可以使用 obj.constructor.name 来检查对象的“类”” developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...,尽管有警告,请参阅stackoverflow.com/questions/ 29310530/…
2021-05-02 07:48:37
很好的解决方案,谢谢!为今天的 JS 更新:const isGenerator = fn => ['GeneratorFunction', 'AsyncGeneratorFunction'].includes(fn.constructor.name). 异步生成器是 ES2018 的一部分,可在 node v10 中使用,请参阅node.green
2021-05-04 07:48:37
这仅适用于函数声明和匿名函数,不适用于命名函数表达式。
2021-05-16 07:48:37

我们在 TC39 面对面会议中讨论过这个问题,并且故意不公开检测函数是否为生成器的方法。原因是任何函数都可以返回一个可迭代对象,所以它是函数还是生成器函数都没有关系。

var iterator = Symbol.iterator;

function notAGenerator() {
  var  count = 0;
  return {
    [iterator]: function() {
      return this;
    },
    next: function() {
      return {value: count++, done: false};
    }
  }
}

function* aGenerator() {
  var count = 0;
  while (true) {
    yield count++;
  }
}

这两个行为相同(减去 .throw() 但也可以添加)

哇...太糟糕了:(无法确定它是生成器函数还是简单函数不允许好的东西,比如与primise库(如Q.async)的集成来自动检测生成器并在那里获取/推送值以获得好的和基于生成器的清理“primise”api。
2021-04-24 07:48:37
@Erik Arvidsson 我们在哪里可以找到 Symbol 函数的文档?
2021-04-24 07:48:37
@LexPodgorny 我发现很少提到符号,这里这里这里
2021-05-08 07:48:37
@Erik,所以你是说生成器函数只是一类特殊的函数,没有什么不同?那么也许我们可以通过检查一个函数是否具有生成器的所有特征(返回包含nextand [iterator]next返回valueandcount等的对象)来判断一个函数是否是一个生成器。在可预见的未来,这会一直有效吗?
2021-05-12 07:48:37
我必须注意,即使使用最新的 Node.js 开发版本,这个代码段也不起作用,我得到了一个Unexpected token [at [iterator]: function() {. 这是从哪里来的?
2021-05-14 07:48:37

这适用于节点和火狐:

var GeneratorFunction = (function*(){yield undefined;}).constructor;

function* test() {
   yield 1;
   yield 2;
}

console.log(test instanceof GeneratorFunction); // true

提琴手

但是如果你绑定一个生成器,它就不起作用,例如:

foo = test.bind(bar); 
console.log(foo instanceof GeneratorFunction); // false
对我来说,在 Chromium 76 和节点 10 中,绑定生成器也能工作。
2021-04-30 07:48:37

我正在使用这个:

var sampleGenerator = function*() {};

function isGenerator(arg) {
    return arg.constructor === sampleGenerator.constructor;
}
exports.isGenerator = isGenerator;

function isGeneratorIterator(arg) {
    return arg.constructor === sampleGenerator.prototype.constructor;
}
exports.isGeneratorIterator = isGeneratorIterator;
我将其缩短为Generator = (function*(){}).constructor; g instanceof Generator,不幸的(function*(){}).prototype.constructor是它不是用于检查生成器迭代器的 instanceof 的有效参数
2021-04-22 07:48:37

TJ Holowaychuk 的co库具有检查某事物是否是生成器函数的最佳功能。这是源代码:

function isGeneratorFunction(obj) {
   var constructor = obj.constructor;
   if (!constructor) return false;
   if ('GeneratorFunction' === constructor.name || 'GeneratorFunction' === constructor.displayName) return true;
   return isGenerator(constructor.prototype);
}

参考:https : //github.com/tj/co/blob/717b043371ba057cb7a4a2a4e47120d598116ed7/index.js#L221