There are two code snippets to show the problem I got.
demo1.js:
// using ES6+ class syntax
class MyObject {
constructor() {
this.myProp1 = 'myProp1';
}
get [Symbol.toStringTag]() {
console.log('[Custom Symbol.toStringTag]]');
return 'CustomTag';
}
static [Symbol.hasInstance](instance) {
console.log('[Custom Symbol.hasInstance]');
return false;
}
}
const myObj = new MyObject();
console.log(Object.prototype.toString.call(myObj)); // works correctly, implicitly called custom getter Symbol.toStringTag
// first log print [Custom Symbol.toStringTag]], then log print [object CustomTag], since custom getter Symbol.toStringTag return 'CustomTag'
console.log(myObj instanceof MyObject); // works correctly, implicitly called custom static method Symbol.hasInstance
// first log print [Custom Symbol.hasInstance], then log print false, since custom static method Symbol.hasInstance return false
demo2.js:
// using classic prototype syntax
function MyObject() {
this.myProp1 = 'myProp1';
}
Object.defineProperty(MyObject.prototype, Symbol.toStringTag, {
configurable: true,
enumerable: true,
get() {
console.log('[Custom Symbol.toStringTag]]');
return 'CustomTag';
}
})
// is this a correct way to define a static method to MyObject by using classic prototype syntax?
MyObject[Symbol.hasInstance] = function (instance) {
console.log('[Custom Symbol.hasInstance]');
return false;
}
const myObj = new MyObject();
console.log(Object.prototype.toString.call(myObj)); // works correctly, implicitly called custom getter Symbol.toStringTag
// first log print [Custom Symbol.toStringTag]], then log print [object CustomTag], since custom getter Symbol.toStringTag return 'CustomTag'
console.log(myObj instanceof MyObject); // does not works correctly, does not implicitly called custom static method Symbol.hasInstance
// just log print true
My Question:
MyObject[Symbol.hasInstance] = function (instance) { ... }
is a correct way to define a static method by using classic prototype syntax?MyObject[Symbol.hasInstance] = function (instance) { ... }
is correct way to define a static method, why the js operator instanceof
does not implicitly call custom static method Symbol.hasInstance?btw, about the well-know Symbol Symbol.hasInstance, pls refer to MDN web page
The problem in your code is that you can't overwrite the Symbol.hasInstance
of a function with a simple assignment.
That is a special case:
Unlike most methods, the
Function.prototype[Symbol.hasInstance]()
property is non-configurable and non-writable. This is a security feature to prevent the underlying target function of a bound function from being obtainable. See this Stack Overflow answer for an example.
MDN Function.prototype[Symbol.hasInstance]()
Description
Here is some evaluation:
function f(v) {
return v === 3;
}
const A = {
[Symbol.hasInstance]: f
}
console.log("2 instanceof A:", 2 instanceof A); // false
console.log("3 instanceof A:", 3 instanceof A); // true
console.log("A[Symbol.hasInstance] === f:", A[Symbol.hasInstance] === f); // true
const B = {};
B[Symbol.hasInstance] = f;
console.log("2 instanceof B:", 2 instanceof B); // false
console.log("3 instanceof B:", 3 instanceof B); // true
console.log("B[Symbol.hasInstance] === f:", B[Symbol.hasInstance] === f); // true
function C() {}
C[Symbol.hasInstance] = f;
C.otherMethod = f;
console.log("2 instanceof C:", 2 instanceof C); // false
console.log("3 instanceof C:", 3 instanceof C); // false
console.log("C.otherMethod(3):", C.otherMethod(3)); // true
console.log("C[Symbol.hasInstance] === f:", C[Symbol.hasInstance] === f); // false
console.log("C.otherMethod === f:", C.otherMethod === f); // true
To overwrite the method, you can use Object.defineProperty
:
function f(v) {
return v === 3;
}
function D() {}
Object.defineProperty(D, Symbol.hasInstance, { value: f});
console.log("2 instanceof D:", 2 instanceof D); // false
console.log("3 instanceof D:", 3 instanceof D); // true
console.log("D[Symbol.hasInstance] === f:", D[Symbol.hasInstance] === f); // true