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

时间:2021-03-17 16:55:37

This question already has an answer here:

这个问题在这里已有答案:

Whats a reliable way to check if a function is a generator, e.g.:

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

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

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

The only way I can think of is fn.toString().startsWith('function*') but that's extremely hacky and unreliable

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

context: nodejs 4+

context:nodejs 4+

1 个解决方案

#1


11  

Erik Arvidsson makes a good point in this answer to an earlier version of this question (it didn't occur to me that it's a dupe), that since any function can return an iterator, there's little point in checking whether a function is a generator or not. That is, there's not much you can do with the information in practical terms, since non-generators can return iterators.

Erik Arvidsson在这个问题的早期版本的答案中提出了一个很好的观点(我没有想到它是一个骗局),因为任何函数都可以返回一个迭代器,所以检查一个函数是否是一个生成器没什么意义或不。也就是说,实际上你可以用信息做很多事情,因为非生成器可以返回迭代器。


I was wrong before, there is a better way than your toString check (if for some reason you have a valid need to do it at all):

之前我错了,有一个比你的toString检查更好的方法(如果由于某种原因你有一个有效的需要完成它):

  1. (Once) Get the value of the default constructor of a generator function, which is specified here. It doesn't have a global like Function and such do.

    (一次)获取生成器函数的默认构造函数的值,此处指定。它没有像函数这样的全局函数。

  2. (Whenever you need to check) Check to see if your target function is instanceof that generator function constructor.

    (每当需要检查时)检查您的目标函数是否是该生成器函数构造函数的实例。

E.g.:

// Once
var GeneratorFunction = (function*(){}).constructor;

// Whenever you need to check
if (fn instanceof GeneratorFunction) {
    // Yep, it's a generator function
}

Old things ruled out:

旧事物排除在外:

I don't see anything in the specification that lets us directly access the [[FunctionKind]] internal slot.

我没有在规范中看到任何可以直接访问[[FunctionKind]]内部插槽的内容。

The spec does say:

该规范确实说:

Unlike function instances, the object that is the value of the a GeneratorFunction’s prototype property does not have a constructor property whose value is the GeneratorFunction instance.

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

So in theory:

所以在理论上:

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

but, that would be incredibly unreliable, as people do things like this all the time (although hopefully less so as people start using class):

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

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

While that Foo.prototype object has a constructor property, it's inherited, not "own". We could do an in check, or a .constructor == fn check, but the above would still mis-identify it. You just can't trust constructor in the wild, people mess it up too much.

虽然那个Foo.prototype对象有一个构造函数属性,但它是继承的,而不是“拥有”。我们可以做一个检查,或.constructor == fn检查,但上面仍然会错误识别它。你不能在野外信任构造函数,人们把它弄得太乱了。

#1


11  

Erik Arvidsson makes a good point in this answer to an earlier version of this question (it didn't occur to me that it's a dupe), that since any function can return an iterator, there's little point in checking whether a function is a generator or not. That is, there's not much you can do with the information in practical terms, since non-generators can return iterators.

Erik Arvidsson在这个问题的早期版本的答案中提出了一个很好的观点(我没有想到它是一个骗局),因为任何函数都可以返回一个迭代器,所以检查一个函数是否是一个生成器没什么意义或不。也就是说,实际上你可以用信息做很多事情,因为非生成器可以返回迭代器。


I was wrong before, there is a better way than your toString check (if for some reason you have a valid need to do it at all):

之前我错了,有一个比你的toString检查更好的方法(如果由于某种原因你有一个有效的需要完成它):

  1. (Once) Get the value of the default constructor of a generator function, which is specified here. It doesn't have a global like Function and such do.

    (一次)获取生成器函数的默认构造函数的值,此处指定。它没有像函数这样的全局函数。

  2. (Whenever you need to check) Check to see if your target function is instanceof that generator function constructor.

    (每当需要检查时)检查您的目标函数是否是该生成器函数构造函数的实例。

E.g.:

// Once
var GeneratorFunction = (function*(){}).constructor;

// Whenever you need to check
if (fn instanceof GeneratorFunction) {
    // Yep, it's a generator function
}

Old things ruled out:

旧事物排除在外:

I don't see anything in the specification that lets us directly access the [[FunctionKind]] internal slot.

我没有在规范中看到任何可以直接访问[[FunctionKind]]内部插槽的内容。

The spec does say:

该规范确实说:

Unlike function instances, the object that is the value of the a GeneratorFunction’s prototype property does not have a constructor property whose value is the GeneratorFunction instance.

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

So in theory:

所以在理论上:

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

but, that would be incredibly unreliable, as people do things like this all the time (although hopefully less so as people start using class):

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

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

While that Foo.prototype object has a constructor property, it's inherited, not "own". We could do an in check, or a .constructor == fn check, but the above would still mis-identify it. You just can't trust constructor in the wild, people mess it up too much.

虽然那个Foo.prototype对象有一个构造函数属性,但它是继承的,而不是“拥有”。我们可以做一个检查,或.constructor == fn检查,但上面仍然会错误识别它。你不能在野外信任构造函数,人们把它弄得太乱了。