Controlla se un costruttore eredita un altro in ES6

Ho una situazione in cui ho bisogno di verificare se un costruttore (X) ha un altro costruttore (Y) nella sua catena prototipo (o è Y stesso).

Il modo più rapido per farlo potrebbe essere (new X()) instanceof Y Questa non è un’opzione in questo caso perché i costruttori in questione possono lanciare se istanziati senza argomenti validi.

Il prossimo approccio che ho considerato è questo:

 const doesInherit = (A, B) => { while (A) { if (A === B) return true; A = Object.getPrototypeOf(A); } return false; } 

Funziona, ma non riesco a scuotere la sensazione che mi manchi un modo più semplice per verificarlo. Ce n’è uno?

A causa del modo in cui funziona instanceof , dovresti essere in grado di farlo

 A.prototype instanceof B 

Ma questo testerebbe solo l’ereditarietà, dovresti confrontare A === B per verificare l’autoreferenzialità:

 A === B || A.prototype instanceof B 

Esempio di Babele :

 class A {} class B extends A {} class C extends B {} console.log(C === C) // true console.log(C.prototype instanceof B) // true console.log(C.prototype instanceof A) // true 

instanceof è fondamentalmente implementato come segue:

 function instanceof(obj, Constr) { var proto; while ((proto = Object.getProtoypeOf(obj)) { if (proto === Constr.prototype) { return true; } } return false; } 

Esso esegue iterazioni sulla catena prototipo dell’object e verifica se uno dei prototipi è uguale alla proprietà prototype del costruttore.

Quindi quasi come quello che stavi facendo, ma internamente.

C’è anche Object.prototype.isPrototypeOf() . Sembra un caso d’uso perfetto, no?

Babele

 class A {} class B extends A {} class C extends B {} console.log(C === C) console.log(B.isPrototypeOf(C)) console.log(A.isPrototypeOf(C)) 

ATTENZIONE: la precedente risposta di controllo delle classi ES6 A, B, C catena ereditaria con isPrototypeOf () funziona alla grande. Ma non funziona come ci si potrebbe aspettare per le classi pre-ES6 Object, Array, Function ecc.

  Object.prototype.isPrototypeOf (Array.prototype); // => true 

Ma:

  Object.isPrototypeOf (Array); // => false 

Questo è come dovrebbe essere. Gli INSTANCES di Array ereditano i metodi di Object.prototype. Ma la matrice “class” NON eredita l’object “class”. Se aggiungi un metodo ad Object non puoi chiamarlo tramite Array. La matrice non eredita i metodi di Object (se presenti). È solo che le classi create dagli utenti funzionano in modo diverso!

Forse non dovremmo pensare a Object, Array e Function come a “classi”, anche se è ansible crearne delle istanze. Sono solo “costruttori”. Oppure possiamo dire che sono classi ma che le classi incorporate in JavaScript funzionano in modo diverso da quelle create dall’utente.