Wie überprüfe ich, ob eine Javascript-Klasse eine andere erbt (ohne ein Objekt zu erstellen)?

78

Z.B:

function A(){}
function B(){}
B.prototype = new A();

Wie kann ich überprüfen, ob die Klasse B die Klasse A erbt?

Simon
quelle

Antworten:

140

Versuche Folgendes:

ChildClass.prototype instanceof ParentClass
Nirvana Tikku
quelle
6
Was ist mit ES6 class ? class A extends B{}wie kann ich dann die Erbteile der Klasse überprüfenA
Omid
5
Die Syntax der @ Omid ES6-Klasse ist meistens genau das: eine spezielle Syntax . Hinter den Kulissen hat sich der tatsächliche Umgang mit "Klassen" nicht geändert und so können Sie immer noch mit A.prototype... developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Thomas Urban
31

Sie können die direkte Vererbung mit testen

B.prototype.constructor === A

Um die indirekte Vererbung zu testen, können Sie Folgendes verwenden:

B.prototype instanceof A

(Diese zweite Lösung wurde zuerst von Nirvana Tikku gegeben)

Denys Séguret
quelle
6
Nein, das überprüft nur die übergeordnete Klasse, nicht die gesamte Heritage-Kette.
Simon
Habe es gerade restauriert. Danke dystroy (für die Aktualisierung dieser Antwort auch)
Nirvana Tikku
22

Zurück zu 2017:
Überprüfen Sie, ob das für Sie funktioniert

ParentClass.isPrototypeOf(ChildClass)
pery mimon
quelle
Funktioniert perfekt, aber Flusen beschweren sich. Es scheint, dass, wenn das Programm nicht die vollständige Kontrolle über ParentClass hat, das Risiko besteht, dass ParentClass die Antwort vortäuscht. Es erstreckt sich auf alle Prototypfunktionen. Wenn das Programm die vollständige Kontrolle über ParentClass hat, sollte dies kein Problem sein.
Craig Hicks
Wie kann es die Antwort vortäuschen? mit Symbolen? und warum sollten sie das tun, wenn es passiert, wahrscheinlich
absichtlich
"Darüber hinaus können Objekte Eigenschaften haben, die die in Object.prototype integrierten Funktionen beschatten und möglicherweise zu unbeabsichtigtem Verhalten oder Sicherheitslücken bei Denial-of-Service führen."
Craig Hicks
"Zum Beispiel wäre es für einen Webserver unsicher, JSON-Eingaben von einem Client zu analysieren und hasOwnProperty direkt für das resultierende Objekt aufzurufen, da ein böswilliger Client einen JSON-Wert wie {" hasOwnProperty ": 1} senden und den Server zum Absturz bringen könnte Um solche subtilen Fehler zu vermeiden, ist es besser, diese Methoden immer von Object.prototype aus aufzurufen. Beispielsweise sollte foo.hasOwnProperty ("bar") durch Object.prototype.hasOwnProperty.call (foo, "bar") ersetzt werden. "" - eslint.org/docs/rules/no-prototype-builtins
Craig Hicks
Ich bin nicht der Meinung, dass es IMMER ersetzt werden muss. Nur erforderlich, wenn der Programmierer in diesem Fall den Bereich möglicher ParentClass-Werte nicht steuert.
Craig Hicks
1

Fallstricke: Beachten Sie, dass instanceofdies nicht wie erwartet funktioniert, wenn Sie mehrere Ausführungskontexte / Fenster verwenden. Siehe §§ .


Laut https://johnresig.com/blog/objectgetprototypeof/ ist dies eine alternative Implementierung, die identisch ist mit instanceof:

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

Wenn Sie es ändern, um die Klasse direkt zu überprüfen, erhalten Sie:

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


Randnotiz

instanceofselbst prüft ob obj.protoist f.prototype, also:

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

und:

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

und:

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

Wenn es nicht gleich ist, wird Proto im Check gegen Proto von Proto getauscht, dann Proto von Proto von Proto und so weiter. So:

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

und:

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

und:

f=()=>{};
f.prototype=Element.prototype
document.documentElement instanceof f //true
document.documentElement.__proto__.__proto__=[];
document.documentElement instanceof f //false
Pacerier
quelle
In Ihrem geänderten Code-Snippet haben Sie 'C.prototype', obwohl Sie den 'C'-Parameter durch' ParentClass 'ersetzt haben
user251242
1

Ich glaube nicht, dass Simon B.prototype = new A()in seiner Frage gemeint hat , denn dies ist sicherlich nicht der Weg, um Prototypen in JavaScript zu verketten.

Angenommen, B erweitert A, verwenden Sie Object.prototype.isPrototypeOf.call(A.prototype, B.prototype)

jlchereau
quelle