J'ai récemment découvert la Object.create()
méthode en JavaScript, et j'essaie de déduire en quoi elle est différente de la création d'une nouvelle instance d'un objet avec new SomeFunction()
, et quand vous souhaitez utiliser l'une par rapport à l'autre.
Prenons l'exemple suivant:
var test = {
val: 1,
func: function() {
return this.val;
}
};
var testA = Object.create(test);
testA.val = 2;
console.log(test.func()); // 1
console.log(testA.func()); // 2
console.log('other test');
var otherTest = function() {
this.val = 1;
this.func = function() {
return this.val;
};
};
var otherTestA = new otherTest();
var otherTestB = new otherTest();
otherTestB.val = 2;
console.log(otherTestA.val); // 1
console.log(otherTestB.val); // 2
console.log(otherTestA.func()); // 1
console.log(otherTestB.func()); // 2
Notez que le même comportement est observé dans les deux cas. Il me semble que les principales différences entre ces deux scénarios sont:
- L'objet utilisé dans
Object.create()
en fait le prototype du nouvel objet, tandis que dans lesnew Function()
propriétés / fonctions déclarées ne forment pas le prototype. - Vous ne pouvez pas créer de fermetures avec la
Object.create()
syntaxe comme vous le feriez avec la syntaxe fonctionnelle. Ceci est logique étant donné la portée de type lexical (vs bloc) de JavaScript.
Les déclarations ci-dessus sont-elles correctes? Et est-ce que je manque quelque chose? Quand utiliseriez-vous l'un sur l'autre?
EDIT: lien vers la version jsfiddle de l'exemple de code ci-dessus: http://jsfiddle.net/rZfYL/
Réponses:
Oui,
Object.create
construit un objet qui hérite directement de celui passé comme premier argument.Avec les fonctions constructeur, l'objet nouvellement créé hérite du prototype du constructeur, par exemple:
Dans l'exemple ci-dessus,
o
hérite directement deSomeConstructor.prototype
.Il y a une différence ici, avec
Object.create
vous pouvez créer un objet qui n'hérite de rien, d'Object.create(null);
autre part, si vous définissezSomeConstructor.prototype = null;
l'objet nouvellement créé héritera deObject.prototype
.Eh bien, vous pouvez créer des fermetures, par exemple en utilisant l'argument des descripteurs de propriété:
Notez que je parle de la
Object.create
méthode ECMAScript 5th Edition , pas de la cale de Crockford.La méthode commence à être implémentée nativement sur les derniers navigateurs, consultez ce tableau de compatibilité .
la source
foo;
est résolu dans l' environnement lexical actuel . 2) Pour fournir un moyen facile d'implémenter l'héritage, c'est une construction vraiment puissante. IMO Je l'utiliserais parce qu'il est vraiment simple et léger, mais pour le code de production, nous devons encore attendre un certain temps avant que ES5 ne soit largement pris en charge. A propos des fonctionnalités manquantes, le fait de créer un objet "vierge",Object.create(null);
manquait, il est vraiment utile d'implémenter des objets fiables de type table de hachage ...Object.create(null)
signifie donc que vous n'avez pas à utiliser dehasOwnProperty()
conneries lors de l'itération car il n'en hérite pas ??? J'aime ça - merci. Bien sûr, tout le monde va encore le fairehasOwnProperty
car tout le monde n'utilisera pas,Object.create(null)
donc je ne suis pas sûr que ce soit un réel avantage ... Jusqu'à présent, j'ai trouvé les autres "avantages" deObject.create()
complètement peu convaincants.Très simplement,
new X
c'estObject.create(X.prototype)
en plus d'exécuter laconstructor
fonction. (Et donner laconstructor
chance àreturn
l'objet réel qui devrait être le résultat de l'expression au lieu dethis
.)C'est ça. :)
Les autres réponses sont tout simplement déroutantes, car apparemment personne d'autre ne lit la définition de l'une
new
ou l'autre. ;)la source
Voici les étapes qui se produisent en interne pour les deux appels:
(indice: la seule différence est à l'étape 3)
new Test()
:new Object()
objobj.__proto__
surTest.prototype
return Test.call(obj) || obj; // normally obj is returned but constructors in JS can return a value
Object.create( Test.prototype )
new Object()
objobj.__proto__
surTest.prototype
return obj;
Donc, en gros,
Object.create
n'exécute pas le constructeur.la source
new
essentiellement toutes les fonctions dupliquées, tandisObject.create
que non.Permettez-moi d'essayer d'expliquer (plus sur Blog ):
Car
constructeurvar Car = function(){}
, voici comment les choses se passent en interne: nous avons un{prototype}
lien caché versFunction.prototype
lequel n'est pas accessible et unprototype
lien versCar.prototype
lequel est accessible et a un réelconstructor
deCar
. Function.prototype et Car.prototype ont des liens cachés versObject.prototype
.Lorsque nous voulons créer deux objets équivalents en utilisant l'
new
opérateur et lacreate
méthode, nous devons le faire comme ceci:Honda = new Car();
etMaruti = Object.create(Car.prototype)
. Qu'est-ce qui se passe?Honda = new Car();
- Lorsque vous créez un objet comme celui-ci, la{prototype}
propriété masquée est pointéeCar.prototype
. Donc, ici, l'{prototype}
objet de Honda sera toujoursCar.prototype
- nous n'avons aucune option pour changer la{prototype}
propriété de l'objet. Et si je veux changer le prototype de notre objet nouvellement créé?Maruti = Object.create(Car.prototype)
- Lorsque vous créez un objet comme celui-ci, vous avez une option supplémentaire pour choisir la{prototype}
propriété de votre objet . Si vous souhaitez que Car.prototype soit le,{prototype}
passez-le en tant que paramètre dans la fonction. Si vous ne voulez pas{prototype}
alors pour votre objet , vous pouvez passernull
comme ceci:Maruti = Object.create(null)
.Conclusion - En utilisant la méthode,
Object.create
vous avez la liberté de choisir la{prototype}
propriété de votre objet . Ennew Car();
, vous n'avez pas cette liberté.Manière préférée dans OO JavaScript:
Supposons que nous ayons deux objets
a
etb
.Supposons maintenant que
a
certaines méthodesb
souhaitent également accéder. Pour cela, nous avons besoin de l'héritage des objets (a
ne devrait être le prototypeb
que si nous voulons accéder à ces méthodes). Si nous vérifions les prototypesa
etb
nous découvrirons qu'ils partagent le prototypeObject.prototype
.Problème - nous voulons
a
que l' objet soit le prototype deb
, mais ici nous avons créé un objetb
avec le prototypeObject.prototype
. Solution - ECMAScript 5 introduitObject.create()
, pour réaliser facilement un tel héritage. Si nous créons un objetb
comme celui-ci:puis,
Donc, si vous faites des scripts orientés objet, cela
Object.create()
est très utile pour l'héritage.la source
a.isPrototypeOf(b);
cela reviendra,false
ce qui est vrai, car les deux objets sont différents et pointent vers une mémoire différente. La bonne façon de le faire avec l'new
opérateur est ici. - jsfiddle.net/167onunp .Cette:
et
sont assez similaires. Une différence importante est que
new Foo
le code constructeur s'exécute réellement, alorsObject.create
qu'il n'exécutera pas de code tel queNotez que si vous utilisez la version à deux paramètres de,
Object.create()
vous pouvez faire des choses beaucoup plus puissantes.la source
Object.create
dans sa forme la plus simple comme celle-ci vous permet d'omettre les fonctions constructeur de votre code tout en profitant de l'héritage du prototype.La différence est ce que l'on appelle «l'hérédité pseudoclassique vs prototypique». La suggestion est d'utiliser un seul type dans votre code, sans mélanger les deux.
Dans l'héritage pseudoclassique (avec "nouvel" opérateur), imaginez que vous définissez d'abord une pseudo-classe, puis créez des objets à partir de cette classe. Par exemple, définissez une pseudo-classe "Personne", puis créez "Alice" et "Bob" à partir de "Personne".
Dans l'héritage prototypique (en utilisant Object.create), vous créez directement une personne spécifique "Alice", puis créez une autre personne "Bob" en utilisant "Alice" comme prototype. Il n'y a pas de "classe" ici; tous sont des objets.
En interne, JavaScript utilise "l'héritage prototypique"; la manière "pseudoclassique" est juste du sucre.
Voir ce lien pour une comparaison des deux façons.
la source
Sommaire:
1) avec le
new
mot-clé il y a deux choses à noter;a) la fonction est utilisée comme constructeur
b) l'
function.prototype
objet est passé à la__proto__
propriété ... ou là où il__proto__
n'est pas pris en charge, c'est le deuxième endroit où le nouvel objet cherche à trouver des propriétés2) avec
Object.create(obj.prototype)
vous construisez un objet (obj.prototype
) et passez-le à l'objet prévu .. avec la différence que maintenant le nouvel objet__proto__
pointe également vers obj.prototype (veuillez vous reporter à xj9 pour cela)la source
Variantes de création d'objets.
Variante 1 : ' new Object () ' -> Constructeur d'objet sans arguments.
Variante 2 : ' nouvel objet (personne) ' -> Constructeur d'objet avec argument.
Variante 3.1 : « Object.create (person) ». Utilisez Object.create avec un simple objet 'personne'. 'Object.create (person)' va créer (et retourner) un nouvel objet vide et ajouter la propriété '__proto__' au même nouvel objet vide. Cette propriété '__proto__' pointera vers l'objet 'personne'.
Variante 3.2 : « Object.create (Object.prototype) ». Utilisez Object.create avec un objet intégré -> 'Object.prototype'. 'Object.create (Object.prototype)' va créer (et retourner) un nouvel objet vide et ajouter la propriété '__proto__' au même nouvel objet vide. Cette propriété '__proto__' pointera vers l'objet 'Object.prototype'.
Variante 4 : ' new SomeFunction () '
la source
En interne,
Object.create
cela:La syntaxe enlève juste l'illusion que JavaScript utilise l'héritage classique.
la source
Object.create
méthode ECMAScript 5 fait beaucoup plus que cela, vous pouvez définir des propriétés par des descripteurs de propriétés et vous pouvez créer un objet qui n'hérite de rien (Object.create(null);
), ce type de shims doit être évité car vous ne pouvez pas vraiment émuler cela comportement sur ES3. Plus d'infosObject.create
.En conséquence, cette réponse et ce
new
mot clé vidéo font les choses suivantes:Crée un nouvel objet.
Lie le nouvel objet à la fonction constructeur (
prototype
).Fait
this
pointer la variable vers le nouvel objet.Exécute la fonction constructeur en utilisant le nouvel objet et la performance implicite
return this
;Attribue le nom de la fonction constructeur à la propriété du nouvel objet
constructor
.Object.create
effectue seulement1st
et2nd
étapes !!!la source