检测 JavaScript 中的直接实例

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

几年前,我想弄清楚如何为类

A
创建类型检查,并为由
true
实例化的对象返回 new A()
only
。为此,我这样写了这个类:

class A {
  static #instances = new WeakSet();

  static isInstance (value) {
    return A.#instances.has(value);
  }

  constructor () {
    if (new.target === A) {
      A.#instances.add(this);
    }
  }
}

扩展

A
的类的任何实例在传递给
false
时都会返回
A.isInstance
。但是,后来我意识到这可以通过使用
Reflect.construct(B, [], A)
来伪造。然后,我所做的是创建一个代理,如果满足某些条件,其
construct
陷阱只会将
A
作为
newTarget
传递。我一直在尝试回忆那个条件是什么,但在尝试重新发现它时,我开始认为我的旧解决方案可能不起作用。

这里有什么方法可以达到我想要的效果吗?

javascript es6-class es6-proxy
1个回答
0
投票

似乎没有明显的干净方法来做到这一点

  1. 你可以猴子补丁
    Reflect.construct
    来捕捉原型被覆盖的情况
  2. 您可以尝试检查调用堆栈并查看调用者是否是另一个构造函数(应该在类的范围内可用(这可能有问题)):

class A {
  static #instances = new WeakSet();

  static isInstance (value) {
    return A.#instances.has(value);
  }

  constructor() {

    if (new.target === A) {
      try{
        throw new Error;
      }catch(e){
        // parse function names (in FF the stack is different)
        const [a, b] = e.stack.match(/\w+(?=\s*\()/gm);
        const fn = eval(b);
        if(fn?.toString().includes('extends A')) return;
      }
      A.#instances.add(this);
    }
  }
}

class B extends A{}

const b = Reflect.construct(B, [], A);
console.log(A.isInstance(b));

const a = new A;
console.log(A.isInstance(a));

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