有两个代码片段显示了我遇到的问题。
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
我的问题:
MyObject[Symbol.hasInstance] = function (instance) { ... }
是使用经典原型语法定义静态方法的正确方法吗?MyObject[Symbol.hasInstance] = function (instance) { ... }
是定义静态方法的正确方法,为什么js运算符instanceof
不隐式调用自定义静态方法Symbol.hasInstance?btw,关于大家熟知的Symbol Symbol.hasInstance,请参考MDN网页
代码中的问题是您无法通过简单的赋值覆盖函数的
Symbol.hasInstance
。
这是一个特殊情况:
与大多数方法不同,
属性是不可配置且不可写的。这是一项安全功能,可防止绑定函数的底层目标函数不可获取。有关示例,请参阅此 Stack Overflow 答案。Function.prototype[Symbol.hasInstance]()
Function.prototype[Symbol.hasInstance]()
描述
以下是一些评价:
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
要覆盖该方法,可以使用
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