Je ne peux tout simplement pas comprendre pourquoi, dans l'héritage d'objets, "instanceof" ne parvient pas à évaluer les objets "enfants" en tant qu'instances de prototypes parents. Par exemple:

function Parent(property) {
    this.property = property;
}

function Child(property) {
    Parent.call(property);
}

const child = new Child("");

console.log(child instanceof Child); // of course, true
console.log(child instanceof Parent); // false. But why???

Quant à l'héritage des classes (ou plutôt de ce qui est réputé être des classes dans JS), la situation est différente :

class Parent {
    constructor(property) {
        this.property = property;
    }
}

class Child extends Parent {
    constructor(property) {
        super(property);
    }
}

const child = new Child("");

console.log(child instanceof Child); // true
console.log(child instanceof Parent); // also true!!!

Quelle est la cause de cette différence ? Est-il possible de créer des objets-enfants afin qu'ils soient correctement reconnus comme instances de leurs prototypes parents (sans recourir à des classes) ?

0
rvk220 10 nov. 2020 à 22:57

1 réponse

Meilleure réponse

Votre premier exemple n'est tout simplement pas très proche du fonctionnement de "l'héritage prototype" en Javascript.

D'une part, Parent.call(property) n'est sûrement pas ce que vous vouliez dire. Cela appelle Parent avec son this défini sur property, et aucun argument passé, ce qui n'est certainement pas ce que vous voulez. Je suppose que vous voulez dire Parent.call(this, property) - qui appelle Parent avec le même this que celui transmis à Child, et en passant par l'argument property. Mais cela n'a rien à voir avec "l'héritage".

L'opérateur instanceof vérifie simplement le " chaîne de prototypes" pour voir si l'objet pertinent (la propriété prototype de la "classe" sur laquelle vous testez) apparaît quelque part. La seule façon de manipuler des objets pour affecter l'opérateur instanceof est de modifier la chaîne de prototypes.

Il existe un certain nombre de façons de le faire, mais la façon standard de "truquer" quelque chose comme l'héritage basé sur les classes dans JS, pré-ES6, aurait été comme ceci :

function Parent(property) {
    this.property = property;
}

function Child(property) {
}

Child.prototype = Object.create(Parent.prototype);

const child = new Child("");

console.log(child instanceof Child);
console.log(child instanceof Parent);

Qui fait manuellement que tous les objets construits à partir de Child délèguent à Object.create(Parent.prototype), qui est lui-même un objet (autrement complètement vide et sans propriétés spéciales) qui "hérite" de Parent.prototype. Alors maintenant, lorsque instanceof vérifie la chaîne de prototypes, il trouve ce qu'il cherche et renvoie donc true, comme vous pouvez le voir dans l'extrait ci-dessus.

Bien sûr, si vous voulez vraiment un héritage basé sur les classes en JS (ce que je ne recommanderais personnellement pas, mais qui est certainement populaire), la syntaxe ES6 class donne un sucre syntaxique beaucoup plus agréable afin que vous n'ayez pas à le faire. gâcher manuellement la chaîne prototype comme ci-dessus. Mais sachez que c'est essentiellement ce qui se passe "sous le capot" avec les classes ES6.

Je recommande fortement ce livre (disponible gratuitement pour lecture en ligne) pour des explications beaucoup plus approfondies de tout cela. Le chapitre 5 est le plus pertinent dans ce contexte.

4
Robin Zigmond 10 nov. 2020 à 20:12