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?

Antworten:



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)


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)

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


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)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.