À L'Aide De L'Objet.attribuer et de l'Objet.créer pour l'héritage
J'ai généralement de mettre en œuvre l'héritage le long des lignes suivantes.
function Animal () { this.x = 0; this.y = 0;}
Animal.prototype.locate = function() {
console.log(this.x, this.y);
return this;
};
Animal.prototype.move = function(x, y) {
this.x = this.x + x;
this.y = this.y + y;
return this;
}
function Duck () {
Animal.call(this);
}
Duck.prototype = new Animal();
Duck.prototype.constructor = Duck;
Duck.prototype.speak = function () {
console.log("quack");
return this;
}
var daffy = new Duck();
daffy.move(6, 7).locate().speak();
J'ai lu ce post par Eric Elliott et si j'ai bien compris je peux utiliser Object.create
et Object.assign
à la place? Est-ce vraiment si simple?
var animal = {
x : 0,
y : 0,
locate : function () {
console.log(this.x, this.y);
return this;
},
move : function (x, y) {
this.x = this.x + x;
this.y = this.y + y;
return this;
}
}
var duck = function () {
return Object.assign(Object.create(animal), {
speak : function () {
console.log("quack");
return this;
}
});
}
var daffy = duck();
daffy.move(6, 7).locate().speak();
Que d'un côté, par convention constructeur fonctions sont capitalisés, devrait objet littéraux de cette loi que les constructeurs également être capitalisés?
J'ai réaliser il y a beaucoup de questions à discuter new
contre Object.create
, mais en général, ils semblent se rapporter à l' Duck.prototype = new Animal();
contre Duck.prototype = Object.create(Animal.prototype);
Si vous utilisez ES2015, vous devriez être en utilisant
ça n'est évidemment pas la question qu'il a posée. Si l'utilisation de
dois-je utiliser
J'ai ajouté de l'ES6 tag dans ce depuis la principale question est de puis-je utiliser l'Objet.créer et Objet.attribuer.
Suivant ce modèle vous préférez
class
& extend
ça n'est évidemment pas la question qu'il a posée. Si l'utilisation de
class
et extend
est une bonne idée est partie d'un autre débat.dois-je utiliser
class
et extend
? Si je fais ce que je finis par avoir à utiliser new
n'est-ce pas? Quels sont les avantages d'utiliser class
et extend
ont plus de Object.assign(Object.create(...
?J'ai ajouté de l'ES6 tag dans ce depuis la principale question est de puis-je utiliser l'Objet.créer et Objet.attribuer.
Suivant ce modèle vous préférez
var duck = Object.assign(Object.create
et var daffy = Object.create(duck)
.OriginalL'auteur user5325596 | 2015-11-13
Vous devez vous connecter pour publier un commentaire.
Oui, c'est aussi simple que cela. Dans votre exemple avec
Object.create/Object.assign
, vous êtes à l'aide d'une fonction de fabrication de créer de nouvelles instances deduck
(de la même façon jQuery crée de nouvelles instances si vous sélectionnez un élément avecvar body = $('body')
). Un avantage de ce style de code, c'est qu'elle ne vous force pas à appeler un constructeur deanimal
lorsque vous souhaitez créer un nouveauduck
instance (par opposition à ES2015 Classes).Différences dans l'initialisation de la
Peut-être une information intéressante qui fonctionne un peu différemment que si vous deviez utiliser un constructeur (ou toute autre fonction d'initialisation):
Lorsque vous créez un
duck
instace, toutes les propriétés deanimal
sont dans le[[Prototype]]
fente de laduck
instance.Donc
daffy
n'a pas de proprex
ety
propriétés encore. Toutefois, lorsque vous appelez la suite, ils seront ajoutés:Pourquoi? Dans la fonction-corps de
animal.move
, nous avons la déclaration suivante:Ainsi, lorsque vous appelez cela avec
daffy.move
,this
se réfère àdaffy
. Donc, il va essayer d'attribuerthis.x + x
àthis.x
. Depuisthis.x
n'est pas encore défini, le[[Prototype]]
de la chaîne dedaffy
est traversée vers le bas pouranimal
, oùanimal.x
est défini.Ainsi, dans le premier appel, le
this.x
sur le côté droit de la cession se réfère àanimal.x
, parce quedaffy.x
n'est pas défini. La deuxième foisdaffy.move(1,2)
est appelé,this.x
sur le côté droit seradaffy.x
.Syntaxe Alternative
Sinon, vous pouvez également utiliser
Object.setPrototypeOf
au lieu deObject.create/Object.assign
(OLOO Style):Conventions De Nommage
Je ne suis pas au courant de toutes les conventions établies. Kyle Simpson utilise des majuscules dans OLOO, Eric Elliot semble utiliser des minuscules. Personnellement je m'en tiendrais à bas-de-casse, parce que l'objet des littéraux de cette loi que les constructeurs sont déjà à part entière des objets eux-mêmes (et pas seulement modèle, comme pour les classes).
Singleton
Si vous ne souhaitais qu'une seule instance (par exemple, pour un singleton), vous pouvez simplement appeler directement:
Object.assign(Object.create
sursetPrototypeOf
est que je peux faire plus easiliy faire "l'héritage multiple" (faute d'un meilleur terme) e.gObject.assign(Object.create(animal), duckObj, someOtherObj, anotherObj)
? Quels sont les inconvénients deObject.assign(Object.create
?Object.assign(Object.create(animal), duckObj, someOtherObj, anotherObj)
est plus un mixin mélangé avec de prototypes 🙂 L'objet résultant contient les propriétés de duckObj, someOtherObj et anotherObj et n'aurait animale dans le [[Prototype]] slot.Si vous voulez avoir de multiples objets dans la chaîne de prototype, vous auriez à les mélanger ensemble dans
Object.create
:Object.assign(Object.create({animal: animal, bird: bird}), duck);
ouObject.setPrototypeOf(duck, {animal: animal, bird: bird});
Je ne suis pas au courant de tout les désavantages de l'utilisation
Object.assign/Object.create
, sauf pour un petit qui a probablement l'habitude de la matière dans la plupart des cas: les Objets créés à l'aide deObject.create
(par opposition ànew
) ne pas profit dehiddenClass
support dans les navigateurs: medium.com/javascript-scene/...Ce commentaire
If you want to have multiple objects in the prototype chain,
m'a fait me demander comment j'allais instancierdaffy
si je voulaisanimal.isPrototypeOf(daffy)
etbird.isPrototypeOf(daffy)
à la fois return true?OriginalL'auteur nils
Oui,
create
etassign
est beaucoup plus simple parce qu'ils sont primitifs, et moins de la magie se passe - tout ce que vous faites est explicite.Cependant, Eric
mouse
exemple est un peu déroutant, car il part d'une étape, et mêle l'héritage de souris à partir d'animaux avec l'instanciation de souris.Plutôt essayons de transcrire votre canard exemple de nouveau - commençons par faire littéralement:
Vous devriez voir que ce qui se passe ici n'est pas vraiment différent de l'utilisation de constructeurs (ou
class
syntaxe), nous avons simplement stockés nos prototypes directement dans les variables et nous faisons de l'instanciation avec un appel explicite àcreate
etconstructor
.Maintenant vous pouvez comprendre que notre
duck.constructor
ne fait rien, mais l'appel de sa méthode super, alors, nous pouvons omettre complètement et laisser l'héritage de faire son travail:L'autre chose qui est souvent changé, c'est l'initialisation de propriétés d'une instance. Il n'y a effectivement aucune raison de réagir si nous n'avons pas vraiment besoin d'eux, il suffit de mettre quelques valeurs par défaut sur le prototype:
Le problème, c'est que elle ne fonctionne que pour des valeurs primitives, et ça devient répétitif. C'est là que l'usine de fonctions se dans:
Pour faciliter l'héritage, l'initialisation n'est souvent pas faite dans l'usine, mais dans une méthode spécifique de sorte qu'il peut être appelé "sous-classe" instances. Vous pouvez appeler cette méthode
init
, ou vous pouvez appeler cela deconstructor
comme je l'ai fait ci-dessus, c'est fondamentalement la même.Si vous ne l'utilisez pas tout les constructeurs, vous pouvez attribuer un nouveau sens à la majuscule des noms de variables, oui. Il peut cependant être source de confusion pour tous ceux qui ne sont pas habitués à cela. Et btw, ils ne sont pas des "objets littéraux qui agissent comme des constructeurs", ils sont juste prototype des objets.
déjà fait. Doit être accepté réponse 🙂
"J'ai lu ce post par Eric Elliott" est l'endroit où vous vous arrêtez et au mépris de tout. Personne n'en sait moins sur une bonne conception que cette grande gueule niais. Tout peut être fait avec les "nouveaux" et "appel" et l '" objet.créer' -- dont le dernier seulement pour l'héritage. L'exemple ci-dessus est donc écrasé comme être singulier preuve de la Dunning Kruger effet. Heureusement ES2015 a rationnellement ajouté étendre et classe de mots clés.
Au lieu d'appeler quelqu'un à une "grande gueule imbécile", vous pouvez argumenter pourquoi
class
,extends
etnew
sont un "meilleur design". J'irais même jusqu'à prétendre qu'ils sont exactement le même design que l'exemple ci-dessus, seulement avec plus de magie sucre syntaxique. Alors, quelle partie est "écrasé"?OriginalL'auteur Bergi
Plutôt que de "l'héritage" vous devez penser à ce type de "l'instanciation d'un modèle de" vous avez l'intention d'utiliser. Ils ont des objectifs différents pour la mise en œuvre.
Le haut exemple prototypes et des bas, fonctionnelle partagée. Consultez ce lien: JS Instanciation des modèles
Aussi, c'est la non-es6 liés.
Object.assign
est ES6.Je ne sais pas pourquoi vous dites "Aussi, c'est la non-es6".
Object.assign
est une partie de l'ES6 standard.ES6-nouvelles normes pour ce que vous êtes essentiellement en utilisant comme
classes
. Le code affiché est spécifiquement lié à l'ES5.si vous vérifier le lien dans ma réponse initiale, vous verrez de quoi je parle.
Non, il n'est pas spécifiquement liés à l'ES5 (voir les deux commentaires ci-dessus,
Object.assign
n'existe pas dans l'ES5). Et leObject.create/Object.assign
combo est un bon modèle dans l'ES6. Et, comme indiqué ci-dessus, votre lien ne concerne pas leObject.create/Object.assign
cas, il ne parle que de laObject.create
en conjonction avec lax.prototype
. C'est précisément ce que l'OP n'est PAS en demandant au sujet.OriginalL'auteur Shinobi881