MindlessRanger MindlessRanger - 3 months ago 10
Javascript Question

Well known Symbols do not work with functions

Consider the following two snippets:

obj = {}; // can be [], Number(), eg. but not Function()
obj[Symbol.hasInstance] = () => console.log('89');
({}) instanceof obj;


and

obj = function() {}; // new Function() too
obj[Symbol.hasInstance] = () => console.log('89');
({}) instanceof obj;


Both should log '89' but only in the first snippet '89' is logged.

In Chrome 52, first logs 89, second logs nothing.

In node v6.3.1 first results in
TypeError: Expecting a function in instanceof check, but got #<Object>
, while second logs nothing.

Is this a bug? What is the intended behaviour? On MDN there is nothing explaining this.

Answer

The [Symbol.hasInstance] property of function is not writable and not configurable:

enter image description here

The spec says:

This property is non-writable and non-configurable to prevent tampering that could be used to globally expose the target function of a bound function.

For that reason, the assignment

obj[Symbol.hasInstance] = () => console.log('89');

silently fails. It doesn't matter that the property is defined on the prototype, if it's not writable it cannot be overwritten by "descendants" either.

So the Chrome behavior is correct.


As for Node, it seems it doesn't implement the new behavior of instanceof yet, i.e. it doesn't use [Symbol.hasInstance] if it exists. In that case the right operand has to be a function, which is not the case in the first example.