How to check if a variable is a generator function? (e.g. function * exit)

What a reliable way to check if a function is a generator, for example:

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 it is extremely hacky and unreliable

context: nodejs 4+

+7
javascript ecmascript-6
source share
1 answer

Eric Arvidson makes a good answer in this answer to an earlier version of this question (it never occurred to me that this is a hoax), since a function can return an iterator, it makes little sense to check if a function is a generator or not. That is, little can be done with the information in practical terms, since non-generators can return iterators.


I used to be wrong, there is a better way than your toString check (if for some reason you really need to do this at all):

  • (Once) Get the default constructor the generator function that is listed here . It does not have a global Function type, and it is possible.

  • (Whenever you need to check) Check if your target function instanceof constructor of the generator function.

eg:.

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

Old things are excluded:

I don’t see anything in the specification, which allows us to directly access the internal [[FunctionKind]] slot.

The specification says :

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

So, in theory:

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

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

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

Although this Foo.prototype object has a constructor property, it is inherited, not "native." We could do an in check or a .constructor == fn check, but the above would still incorrectly identify it. You simply cannot trust the constructor in the wild, people have mixed up too much.

+11
source share

All Articles