web-dev-qa-db-fra.com

Héritage JavaScript: Object.create vs new

En JavaScript, quelle est la différence entre ces deux exemples:

Prérequis:

function SomeBaseClass(){
}

SomeBaseClass.prototype = {
    doThis : function(){
    },

    doThat : function(){
    }
}

Exemple d'héritage A utilisant Object.create:

function MyClass(){
}

MyClass.prototype = Object.create(SomeBaseClass.prototype);

Exemple d'héritage B utilisant le nouveau mot clé

function MyClass(){
}

MyClass.prototype = new SomeBaseClass();

Les deux exemples semblent faire la même chose. Quand choisiriez-vous l'un sur l'autre?

Une question supplémentaire: Considérons le code dans le lien ci-dessous (ligne 15), où une référence au constructeur de la fonction est stockée dans le prototype. Pourquoi est-ce utile?

https://github.com/mrdoob/three.js/blob/master/src/loaders/ImageLoader.js

Extrait (si vous ne voulez pas ouvrir le lien):

THREE.ImageLoader.prototype = {

    constructor: THREE.ImageLoader
}
116
ChrisRich

Dans votre question, vous avez mentionné que Both examples seem to do the same thing, Ce n'est pas vrai du tout, car

Votre premier exemple

function SomeBaseClass(){...}
SomeBaseClass.prototype = {
    doThis : function(){...},
    doThat : function(){...}
}
function MyClass(){...}
MyClass.prototype = Object.create(SomeBaseClass.prototype);

Dans cet exemple, vous héritez simplement de SomeBaseClass' prototype mais que se passe-t-il si vous avez une propriété dans votre SomeBaseClass comme

function SomeBaseClass(){ 
    this.publicProperty='SomeValue'; 
}

et si vous l'utilisez comme

var obj=new MyClass();
console.log(obj.publicProperty); // undefined
​console.log(obj);​

L'objet obj n'aura pas la propriété publicProperty comme dans cet exemple .

Votre deuxième exemple

MyClass.prototype = new SomeBaseClass();

Il exécute la fonction constructor, crée une instance de SomeBaseClass et hérite de l'intégralité de l'objet SomeBaseClass. Donc, si vous utilisez

    var obj=new MyClass();
    console.log(obj.publicProperty); // SomeValue
    console.log(obj);​

Dans ce cas, sa propriété publicProperty est également disponible pour l'objet obj comme dans cet exemple .

Le Object.create n'étant pas disponible dans certains anciens navigateurs, vous pouvez dans ce cas utiliser

if(!Object.create)
{
    Object.create=function(o){
        function F(){}
        F.prototype=o;
        return new F();
    }
}

Le code ci-dessus ajoute simplement la fonction Object.create si elle n’est pas disponible, vous pouvez donc utiliser la fonction Object.create et je pense que le code ci-dessus décrit ce que Object.create fait réellement. J'espère que ça va aider d'une certaine manière.

109
The Alpha

Les deux exemples semblent faire la même chose.

C'est vrai dans ton cas.

Quand choisiriez-vous l'un sur l'autre?

Lorsque SomeBaseClass a un corps de fonction, il sera exécuté avec le mot clé new. Cela n’est généralement pas prévu - vous souhaitez uniquement configurer la chaîne de prototypes. Dans certains cas, cela pourrait même causer de graves problèmes, car vous instanciez un objet dont les variables à portée privée sont partagées par toutes les instances MyClass. ils héritent des mêmes méthodes privilégiées. D'autres effets secondaires sont imaginables.

Donc, vous devriez généralement préférer Object.create. Cependant, il n'est pas pris en charge par certains navigateurs existants. c'est la raison pour laquelle vous voyez l'approche new- beaucoup trop fréquente, car elle ne fait souvent aucun mal (évident). Regardez aussi cette réponse .

39
Bergi

La différence devient évidente si vous utilisez Object.create() comme prévu. En fait, il cache entièrement le mot prototype dans votre code, il fera le travail sous le capot. En utilisant Object.create(), nous pouvons aller comme

var base =  {
    doThis : function(){
    },

    doThat : function(){
    }
};

Et puis nous pouvons étendre/hériter d'autres objets de cette

var myObject = Object.create( base );
// myObject will now link to "base" via the prototype chain internally

Il s’agit donc d’un autre concept, d’une manière d’hériter plus "orientée objet". Il n'y a pas de "fonction constructeur" dans la boîte utilisant Object.create() par exemple. Mais bien sûr, vous pouvez simplement créer et appeler une fonction auto-définie constructeur au sein de ces objets.

Un argument en faveur de l'utilisation de Object.create() est qu'il pourrait sembler que natural ressemble davantage à mix/* hériter * d'autres objets que d'utiliser Javascripts default.

8
jAndy

Je ne suis pas un expert en script Java, mais voici un exemple simple pour comprendre la différence entre "Object.create" et "new".

étape 1: créer la fonction parente avec quelques propriétés et actions ..

function Person() {

this.name = 'venkat';

this.address = 'dallas';

this.mobile='xxxxxxxxxx'

}

Person.prototype.func1 = function () {

    return this.name + this.address;
}

étape 2: créez une fonction enfant (PersonSalary) qui s'étend au-dessus de la fonction Personne à l'aide de Nouveau mot clé ..

function PersonSalary() {
    Person.call(this);
}
PersonSalary.prototype = new Person();

PersonSalary();

étape 3: créer une deuxième fonction enfant (PersonLeaves) qui s'étend au-dessus de la fonction Personne à l’aide de Object.create mot clé ..

function PersonLeaves() {
 Person.call(this);
}
PersonLeaves.prototype = Object.create(Person.prototype);


PersonLeaves();

// Maintenant, vérifiez les deux prototypes de fonctions enfants.

PersonSalary.prototype
PersonLeaves.prototype

ces deux fonctions enfants seront liées au prototype de personne (fonction parent) et pourront accéder à ses méthodes, mais si vous créez une fonction enfant à l'aide de new, un nouvel objet sera renvoyé avec toutes les propriétés parent dont nous n'avons pas besoin, ainsi objet ou fonction utilisant "Nouveau", cette fonction parent est exécutée, ce que nous ne voulons pas être.

Voici les plats à emporter

si vous souhaitez simplement déléguer à certaines méthodes de la fonction parent et ne voulez pas créer un nouvel objet, utilisez Object.create.

0
Venkat