如何检查变量是否是生成器函数? (例如函数*产量)

时间:2015-12-05 08:55:52

标签: javascript node.js ecmascript-6

检查函数是否为生成器的可靠方法,例如:

let fn = function* () {
    yield 100;
}

if (fn instanceof ??) {
   for (let value in fn()) {
       ...
   }
}

我能想到的唯一方法是fn.toString().startsWith('function*'),但这非常黑客且不可靠

context:nodejs 4 +

1 个答案:

答案 0 :(得分:11)

Erik Arvidsson makes a good point in this answer这个问题的早期版本(我没想到它是一个傻瓜),因为任何函数都可以返回一个迭代器,这里有一点点检查函数是否是生成器。也就是说,实际上你对信息的处理力度不大,因为非生成器可以返回迭代器。

之前我错了,toString检查更好的方式(如果由于某种原因你根本不需要这样做):

  1. (一次)获取生成器函数的默认constructor的值,即specified here。它没有像Function那样的全球性,而且没有。{/ p>

  2. (每当您需要检查时)检查您的目标函数是否为instanceof生成器函数构造函数。

  3. E.g:

    // Once
    var GeneratorFunction = (function*(){}).constructor;
    
    // Whenever you need to check
    if (fn instanceof GeneratorFunction) {
        // Yep, it's a generator function
    }
    

    旧事被排除在外:

    我在规范中没有看到任何可以让我们直接访问[[FunctionKind]]内部广告位的内容。

    规范does say

      

    与函数实例不同,作为GeneratorFunction的prototype属性值的对象没有constructor属性,其值为GeneratorFunction实例。

    所以理论上:

    if (!fn.prototype.hasOwnProperty("constructor")) {
        // It's a generator function
    }
    

    但是 ,这将是非常不可靠的,因为人们总是这样做(虽然希望人们开始使用class时不那么喜欢):

    function Foo() {
    }
    Foo.prototype = {
        method: function() {}
    };
    

    虽然Foo.prototype对象具有constructor属性,但它是继承的,而不是"拥有"。我们可以进行in检查或.constructor == fn检查,但上述内容仍会误识别。你无法在野外信任constructor,人们会把它搞得太乱。