问题
So, I was writing some example code implementing another function for Constructor[Symbol.hasInstance]
and I noticed my new implementation just won't get called.
The script below is what I expected to happen:
function Pirate(name) {
this.name = name;
}
const jackSparrow = {
isPirate: true
};
// Notice how `jackSparrow` is not yet considered an instance of the `Pirate` object
console.log(jackSparrow instanceof Pirate); // false
// Now let's assign another function for `Pirate[Symbol.hasInstance]`
Pirate[Symbol.hasInstance] = function (anObj) {
return anObj.isPirate;
};
// This will cause Pirate[Symbol.hasInstance] to be called with `jackSparrow`
console.log(jackSparrow instanceof Pirate); // true
I tried to add a console.log
call to to my Pirate[Symbol.hasInstance] implementation, but it won't log anything to the console.
Does anyone have any idea of what is happening? Why is my implementation not getting called?
I'm running this on Node 6.9.1.
回答1:
You can find the answer if you do
Object.getOwnPropertyDescriptor( Function.prototype, Symbol.hasInstance).writable
It returns false
: you cannot write to the Symbol.hasInstance
property of a function with the assignment =
operator. The property never gets set and so it never gets called. (Failing silently feels like unhelpful behaviour to me, but there you go. A TypeError
is thrown with a helpful message if you are in strict mode, one of the many reasons you should use it all the time.) You can only define the Symbol.hasInstance
property on a function with Object.defineProperty
.
Object.defineProperty(Pirate, Symbol.hasInstance, {
value: function(anObj) {
console.log('Is he a pirate?');
return anObj.isPirate;
}
});
Now jackSparrow instanceof Pirate
first logs the question, then returns true
.
回答2:
@lonesomeday's answer explains the reason. Assignments don't define a property if the object already inherits that property as non-writable.
If you don't want to use explicit property definitions, consider using the class syntax:
class Pirate {
constructor(name) {
this.name = name;
}
static [Symbol.hasInstance](anObj) {
return anObj.isPirate;
}
}
const jackSparrow = {
isPirate: true
};
console.log(jackSparrow instanceof Pirate); // true
来源:https://stackoverflow.com/questions/40982924/reimplemented-constructorsymbol-hasinstance-but-it-still-wont-be-called