比较具有相同父 class 的派生 classes 的实例

Comparing instances of derived classes having the same parent class

我有两个 class 继承同一个父 class,像这样:

class ParentClass{ ... }
class Son extends ParentClass{ ... }
class Daughter extends ParentClass{ ... }

我想要类似于此伪代码的代码:

a.getClass() === b.getClass(); 

如果两个变量都是同一个派生 class 的实例(例如本例中的 SonDaughter),则只有 return 为真。

I'd like to have code similar to this:

typeof a === typeof b

which only returns true if both variables are instances of the same derived class (e.g. Son or Daughter in this example).

不,如果 ab 任何 类型的对象,包括与 [=21 完全无关的对象,则 returns 为真=],因为 typeof 对于任何对象都将是 "object",当然,"object" === "object" 是正确的。

instanceofreturnstrue如果左手操作数的原型链包含右手操作数.prototype属性引用的对象,所以instanceof 将按照您的描述工作:

a instanceof ParentClass === b instanceof ParentClass

实例:

class ParentClass { }
class Son extends ParentClass { }
class Daughter extends ParentClass { }

const a = new Son();
const b = new Daughter();

console.log(a instanceof ParentClass === b instanceof ParentClass); // true

const c = new Son();
const d = new Map(); // Not a ParentClass subclass

console.log(c instanceof ParentClass === d instanceof ParentClass); // false


您在评论中说:

I'd like to find out if two variables are instances of the same derived class. My original question was worded very confusingly, so I edited it.

啊,那你想以两种方式之一使用 constructor 属性。或者:

  1. 查看a是否是与b相同class的实例或子class[= b 中的 85=] 个 class:

    a instanceof b.constructor
    
  2. 查看a是否与b相同class的实例:

    a.constructor === b.constructor
    

constructor属性来自实例的原型;默认情况下,它是对原型对象最初附加到 *(即 Son.prototype.constructor 指的是 Son)的构造函数的引用。

#1 的实例:

class ParentClass { }
class Son extends ParentClass { }
class Daughter extends ParentClass { }

const a = new Son();
const b = new Daughter();

console.log(a instanceof b.constructor); // false

const c = new Son();
const d = new Son();

console.log(c instanceof d.constructor); // true

class SonSubClass extends Son { }

const e = new SonSubClass();
const f = new Son();

console.log(e instanceof f.constructor); // true

#2 的实例:

class ParentClass { }
class Son extends ParentClass { }
class Daughter extends ParentClass { }

const a = new Son();
const b = new Daughter();

console.log(a instanceof b.constructor); // false

const c = new Son();
const d = new Son();

console.log(c instanceof d.constructor); // true

class SonSubClass extends Son { }

const e = new SonSubClass();
const f = new Son();

console.log(e.constructor === f.constructor); // false

如果您希望能够确定两个任意对象是否共享一个共同的祖先,您需要递归地比较两者的原型。

我写了一个函数,可以接受两个 unknown 类型的东西,并会告诉你它们是否有共同的祖先:

function sharesParent(sibling: unknown, possibleSibling: unknown): boolean {
    if (sibling !== null && possibleSibling !== null) {
        const objectPrototype = Object.getPrototypeOf({});
        const functionPrototype = Object.getPrototypeOf(Function);
        let currentSiblingPrototype = Object.getPrototypeOf(sibling);

        while (currentSiblingPrototype !== objectPrototype && currentSiblingPrototype !== functionPrototype) {
            let currentPossibleSiblingPrototype = Object.getPrototypeOf(possibleSibling);

            while (currentPossibleSiblingPrototype !== objectPrototype && currentPossibleSiblingPrototype !== functionPrototype) {
                if (currentPossibleSiblingPrototype === currentSiblingPrototype) {
                    console.log(currentPossibleSiblingPrototype);
                    return true;
                }

                currentPossibleSiblingPrototype = Object.getPrototypeOf(currentPossibleSiblingPrototype);
            }

            currentSiblingPrototype = Object.getPrototypeOf(currentSiblingPrototype);
        }
    }

    return false;
}

class Rock { }
class Granite extends Rock { }
class Limestone extends Rock { }

class Animal { }
class Panda extends Animal { }
class Horse extends Animal { }

class Pony extends Horse { }

console.log(
    sharesParent(new Pony, new Granite) /* false */,
    sharesParent(new Panda, new Pony) /* true */,
    sharesParent(new Pony, new Horse) /* true */,
    sharesParent("string", "secondString") /* true */,
    sharesParent("string", 42) /* false */,
    sharesParent(Map, Set) /* false */,
);

如果您知道要查找的共享祖先是什么,那么使用 T.J 提议的 instanceof 会好很多。克劳德.