Як перевірити, чи клас Javascript успадковує інший (без створення obj)?


Відповіді:


142

Спробуйте наступне:

ChildClass.prototype instanceof ParentClass

6
А як щодо ES6 class ? class A extends B{}тоді як я можу перевірити спадщину класуA
Омід

5
Синтаксис класу @Omid ES6 - це здебільшого саме такий: якийсь спеціальний синтаксис . За лаштунками фактична обробка "класів" не змінилася, і, отже, ви все ще можете працювати з A.prototype... developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Томас Урбан

31

Ви можете перевірити пряме успадкування за допомогою

B.prototype.constructor === A

Для перевірки непрямого успадкування ви можете використовувати:

B.prototype instanceof A

(це друге рішення вперше дала Нірвана Тікку)


6
Ні, це перевірить лише батьківський клас, а не весь ланцюжок спадщини.
Саймон

Щойно його відновили. Дякую дистрою (і за оновлення цієї відповіді теж)
Nirvana Tikku

22

назад до 2017 року:
перевірте, чи це працює для вас

ParentClass.isPrototypeOf(ChildClass)

Працює ідеально, але шкурка скаржиться. Здається, що якщо програма не має повного контролю над ParentClass, тоді існує ризик ParentClass підробити відповідь. Він поширюється на всі функції прототипу. Якщо програма має повний контроль над ParentClass, це не повинно бути проблемою.
Крейг Хікс,

Як це може підробити відповідь? за допомогою символів? і навіщо їм це робити, якщо це трапляється, мабуть, за задумом
pery mimon

"Крім того, об’єкти можуть мати властивості, які затінюють вбудовані елементи Object.prototype, що потенційно може спричинити ненавмисну ​​поведінку або вразливості безпеки відмови в обслуговуванні."
Крейг Хікс,

"Наприклад, веб-серверу було б небезпечно аналізувати вхідні дані JSON від клієнта і викликати hasOwnProperty безпосередньо на отриманий об'єкт, оскільки шкідливий клієнт може надіслати значення JSON, як {" hasOwnProperty ": 1}, і спричинити збій сервера . Щоб уникнути подібних помилок, краще завжди викликати ці методи з Object.prototype. Наприклад, foo.hasOwnProperty ("bar") слід замінити на Object.prototype.hasOwnProperty.call (foo, "bar"). " - eslint.org/docs/rules/no-prototype-builtins
Крейг Хікс,

Я не згоден з тим, що його ЗАВЖДИ потрібно замінити. Це необхідно лише тоді, коли в цьому випадку програміст не контролює діапазон можливих значень ParentClass.
Крейг Хікс,

1

Помилки: Зверніть увагу, що instanceofце не працює належним чином, якщо ви використовуєте кілька контекстів / вікон виконання. Див. §§ .


Крім того, відповідно до https://johnresig.com/blog/objectgetprototypeof/ , це альтернативна реалізація, ідентична instanceof:

function f(_, C) { // instanceof Polyfill
  while (_ != null) {
    if (_ == C.prototype)
      return true;
    _ = _.__proto__;
  }
  return false;
}

Модифікація його для перевірки класу безпосередньо дає нам:

function f(ChildClass, ParentClass) {
  _ = ChildClass.prototype;
  while (_ != null) {
    if (_ == C.prototype)
      return true;
    _ = _.__proto__;
  }
  return false;
}


Сіденоте

instanceofсам перевіряє, чи obj.protoє f.prototype, таким чином:

function A(){};
A.prototype = Array.prototype;
[]instanceof Array // true

і:

function A(){}
_ = new A();
// then change prototype:
A.prototype = [];
/*false:*/ _ instanceof A
// then change back:
A.prototype = _.__proto__
_ instanceof A //true

і:

function A(){}; function B(){};
B.prototype=Object.prototype;
/*true:*/ new A()instanceof B 

Якщо воно не рівне, прото під час перевірки міняється місцями прото прото, потім прото прото прото тощо. Отже:

function A(){}; _ = new A()
_.__proto__.__proto__ = Array.prototype
g instanceof Array //true

і:

function A(){}
A.prototype.__proto__ = Array.prototype
g instanceof Array //true

і:

f=()=>{};
f.prototype=Element.prototype
document.documentElement instanceof f //true
document.documentElement.__proto__.__proto__=[];
document.documentElement instanceof f //false


у вашому зміненому фрагменті коду у вас є "C.prototype", хоча ви замінили параметр "C" на "ParentClass"
user251242

1

Я не думаю, що Саймон мав B.prototype = new A()на увазі у своєму питанні, оскільки це, звичайно, не спосіб ланцюга прототипів у JavaScript.

Якщо припустити, що B продовжує A, використовуйте Object.prototype.isPrototypeOf.call(A.prototype, B.prototype)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.