为什么不能使用简单的属性赋值来定义 [Symbol.hasInstance] 静态方法?

问题描述 投票:0回答:1

有两个代码片段显示了我遇到的问题。

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

我的问题:

  1. 在 demo1.js 中,一切都按预期正常工作。
  2. 在 demo2.js 中,
    MyObject[Symbol.hasInstance] = function (instance) { ... }
    是使用经典原型语法定义静态方法的正确方法吗?
  3. 在demo2.js中,如果
    MyObject[Symbol.hasInstance] = function (instance) { ... }
    是定义静态方法的正确方法,为什么js运算符
    instanceof
    不隐式调用自定义静态方法Symbol.hasInstance?

btw,关于大家熟知的Symbol Symbol.hasInstance,请参考MDN网页

javascript prototype symbols instanceof
1个回答
1
投票

代码中的问题是您无法通过简单的赋值覆盖函数的

Symbol.hasInstance

这是一个特殊情况:

与大多数方法不同,

Function.prototype[Symbol.hasInstance]()
属性是不可配置且不可写的。这是一项安全功能,可防止绑定函数的底层目标函数不可获取。有关示例,请参阅此 Stack Overflow 答案

MDN

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

© www.soinside.com 2019 - 2024. All rights reserved.