Добавьте базовый класс в существующую цепочку прототипов, чтобы instanceof работал

У меня есть существующая иерархия прототипов, и я хочу изменить ее так, чтобы иерархия оставалась нетронутой, но к ее концу добавлялся дополнительный прототип. instanceof должен вернуть true для всех прототипов.

То есть: скажем, у меня есть B->A и я хочу сделать это B->A->Base. Сейчас instanceof должен вернуть true для A, B, Base.

Я пытался использовать B.prototype.prototype и Object.setPrototypeOf(), но безуспешно в любом случае.

Пример с Object.setPrototypeOf():

class A {                                                                                                                                                                                                                            
    do() { console.log("do A"); }                                                                                                                                                                                                                            
}                                                                                                                                                                                                                                    


class B extends A {
    do() { console.log("do B"); }

    doB() { console.log("what"); }
}


var a = new A();
var b = new B();

a.do();
b.do();
b.doB();

console.log(a instanceof A)  // true
console.log(a instanceof B)  // false

console.log(b instanceof A)  // true
console.log(b instanceof B)  // true


class Base {
    doBase() { console.log("this is the base!"); }
}


// now add Base to B's chain, so that B -> A -> Base
// TODO: doesn't work!

Object.setPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(B)), Base.prototype)
//Object.setPrototypeOf(Object.getPrototypeOf(B), Base)


console.log(Object.getPrototypeOf(B))
console.log(Object.getPrototypeOf(Object.getPrototypeOf(B)))


var c = new B();

console.log(c instanceof B)    // true
console.log(c instanceof A)    // true
console.log(c instanceof Base) // false (!!! how to fix it?)

c.doBase();                    // crash, not a function

1 ответ

Решение

Это показывает отношения наследования от B до A;

console.log(Object.getPrototypeOf(B.prototype) === A.prototype);

Итак, учитывая это;

class A { do() { console.log("do A"); } }

class B extends A {
  do() { console.log("do B"); }
  doB() { console.log("what"); }
}

class Base {
  doBase() { console.log("this is the base!"); }
}

Без ссылки на А вам это нужно;

Object.setPrototypeOf(Object.getPrototypeOf(B.prototype), Base.prototype);

Такое что;

console.log(new A() instanceof Base); // true
console.log(new B() instanceof Base); // true
(new B()).doBase(); // this is the base!

Как это? Играть с этим здесь.

Как упомянуто Берги, чтобы выполнить Object.setPrototypeOf(A,Base) таким же образом, как расширение класса без ссылки на A, Object.setPrototypeOf(Object.getPrototypeOf(B.prototype.constructor), Base), (Нужно исследовать это, сообщил, что это вызывает ошибку циклического наследования...)

Здесь расширен тест для выполнения наследования конструктора класса, как показано выше. Работает в Chrome 53 (V8 5.3.332.45).

Изменить: Обратите внимание, это обезьяна-патчирование цепочки наследования.Это не фантастическая идея для производительности.

Другие вопросы по тегам