Je suis actuellement en train de passer de Java à Javascript, et il m'est un peu difficile de comprendre comment étendre les objets comme je le souhaite.
J'ai vu plusieurs personnes sur Internet utiliser une méthode appelée extension sur objet. Le code ressemblera à ceci:
var Person = {
name : 'Blank',
age : 22
}
var Robot = Person.extend({
name : 'Robo',
age : 4
)}
var robot = new Robot();
alert(robot.name); //Should return 'Robo'
Quelqu'un sait-il comment faire fonctionner cela? J'ai entendu dire que tu devais écrire
Object.prototype.extend = function(...);
Mais je ne sais pas comment faire fonctionner ce système. Si ce n'est pas possible, veuillez me montrer une autre alternative qui étend un objet.
extend
fonction, j'ai mis en place un exemple ici: jsfiddle.net/k9LRdRéponses:
Vous voulez 'hériter' de l'objet prototype de Person:
la source
Person()
constructeur est-il appelé lorsque vous le faitesnew Robot()
? Il me semble que vous devriez appeler ce constructeur de classe de base au lieu de le fairethis.name = name;
dans leRobot()
constructeur ...Person.apply(this, arguments);
. Il serait également préférable d'utiliserRobot.prototype = Object.create(Person.prototype);
au lieu denew Person();
.Monde sans le mot-clé «nouveau».
Et une syntaxe plus simple de type "prose" avec Object.create ().
* Cet exemple est mis à jour pour les classes ES6.
Tout d'abord, rappelez-vous que Javascript est un langage prototypique . Ce n'est pas basé sur la classe. Par conséquent, l'écriture sous forme prototypique expose sa vraie nature et peut être très simple, semblable à une prose et puissante.
TLDR;
Non, vous n'avez pas besoin de constructeurs, pas d'
new
instanciation ( lisez pourquoi vous ne devriez pas utilisernew
), nonsuper
, pas de drôle de drôle__construct
. Vous créez simplement des objets, puis les étendez ou les transformez.( Si vous connaissez les getters et les setters, consultez la section "Lectures supplémentaires" pour voir comment ce modèle vous donne des getters et des setters gratuits comme Javascript l'avait initialement prévu, et à quel point ils sont puissants .)
Syntaxe de type prose: Protoype de base
En un coup d'œil, semble très lisible.
Extension, création d'un descendant de
Person
* Les termes corrects sont
prototypes
, et leurdescendants
. Il n'y a pasclasses
et pas besoin deinstances
.Une façon de fournir un moyen "par défaut" de créer un
descendant
, est de joindre une#create
méthode:Les moyens ci-dessous ont une lisibilité inférieure:
Comparer à l'équivalent "classique":
La lisibilité du code en utilisant un style "classique" n'est pas très bonne.
Classes ES6
Certes, certains de ces problèmes sont éradiqués par les classes ES6, mais quand même:
Branchement du prototype de base
Joindre des méthodes uniques à
Robot
Vérification de l'héritage
Vous avez déjà tout ce dont vous avez besoin! Pas de constructeur, pas d'instanciation. Prose propre et claire.
Lectures complémentaires
Écriture, configurabilité et Getters et Setters gratuits!
Pour les getters et les setters gratuits, ou pour une configuration supplémentaire, vous pouvez utiliser le deuxième argument d'Object.create () aka propertiesObject. Il est également disponible dans # Object.defineProperty et # Object.defineProperties .
Pour illustrer à quel point cela est puissant, supposons que nous voulions tous
Robot
être strictement faits de métal (viawritable: false
) et normaliser lespowerConsumption
valeurs (via des getters et des setters).Et tous les prototypes de
Robot
ne peuvent pas êtremadeOf
autre chose parce quewritable: false
.Mixins (en utilisant # Object.assign) - Anakin Skywalker
Pouvez-vous sentir où cela va ...?
Dark Vador obtient les méthodes de
Robot
:Avec d'autres choses étranges:
Eh bien, que Dark Vador soit un homme ou une machine est en effet subjectif:
Extra - Syntaxe légèrement plus courte avec # Object.assign
Selon toute vraisemblance, ce modèle raccourcit votre syntaxe. Mais ES6 # Object.assign peut raccourcir un peu plus (pour polyfill à utiliser sur les navigateurs plus anciens, voir MDN sur ES6 ).
la source
Object.assign(Robot, {a:1}
une bonne alternative à votreextend()
méthode? 2) Comment remplacer lagreet()
méthode pour qu'elle renvoie le même texte, mais avec "un remplacement de salutation" ajouté?#Object.assign
semble être une bonne alternative. Mais la prise en charge du navigateur est inférieure à atm. 2) Vous utiliserez la__proto__
propriété de l'objet pour accéder à la fonction de salutation de son prototype. alors vous appelez la fonction de salutation de prototype avec la portée de l'appelé passée. Dans ce cas, la fonction était un journal de console, il n'est donc pas possible d '«ajouter». Mais avec cet exemple, je pense que vous obtenez la dérive.skywalker.greet = function() { this.__proto__.greet.call(this); console.log('a greet override'); }
Si vous n'avez pas encore trouvé de moyen, utilisez la propriété associative des objets JavaScript pour ajouter une fonction d'extension au
Object.prototype
comme indiqué ci-dessous.Vous pouvez ensuite utiliser cette fonction comme indiqué ci-dessous.
la source
Approche différente: Object.create
Selon la réponse @osahyoun, je trouve ce qui suit comme un moyen meilleur et efficace d'`` hériter '' de l'objet prototype de Person:
Créez de nouvelles instances:
Maintenant, en utilisant Object.create :
Consultez également la documentation MDN .
la source
name
paramètre au constructeur parent, comme ceci: jsfiddle.net/3brm0a7a/3 (la différence est dans la ligne # 8)Dans ES6 , vous pouvez utiliser un opérateur de diffusion comme
Pour plus d'informations, voir le lien MDN -Spread Syntax
Ancienne réponse:
Dans ES6 , il y a
Object.assign
pour copier les valeurs de propriété. Utilisez{}
comme premier paramètre si vous ne souhaitez pas modifier l'objet cible (le premier paramètre est passé).Pour plus de détails, voir lien, MDN - Object.assign ()
Si vous avez besoin d'un Polyfill pour ES5 , le lien le propose également. :)
la source
Et un an plus tard, je peux vous dire qu'il y a une autre bonne réponse.
Si vous n'aimez pas la façon dont le prototypage fonctionne pour s'étendre sur des objets / classes, jetez un œil à ceci: https://github.com/haroldiedema/joii
Exemple de code rapide des possibilités (et bien d'autres):
la source
Les personnes qui luttent encore pour la meilleure approche simple, vous pouvez utiliser
Spread Syntax
pour étendre l'objet.Remarque: n'oubliez pas que la propriété la plus à droite aura la priorité. Dans cet exemple,
person2
est à droite, doncnewObj
aura le nom Robo dedans.la source
Vous voudrez peut-être envisager d'utiliser une bibliothèque d'assistance comme underscore.js , qui a sa propre implémentation de
extend()
.Et c'est aussi un bon moyen d'apprendre en regardant son code source. La page de code source annotée est très utile.
la source
_.extend()
rend sa fonctionnalité assez claire: lostechies.com/chrismissal/2012/10/05/…Mozilla 'annonce' un objet s'étendant d'ECMAScript 6.0:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends
REMARQUE: Il s'agit d'une technologie expérimentale faisant partie de la proposition ECMAScript 6 (Harmony).
Cette technologie est disponible dans Gecko (Google Chrome / Firefox) - versions nocturnes 03/2015.
la source
Dans la majorité des projets, il existe une implémentation de l'extension d'objet: soulignement, jquery, lodash: extend .
Il existe également une implémentation javascript pure, qui fait partie d'ECMAscript 6: Object.assign : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
la source
Ensuite:
Mise à jour 01/2017:
S'il vous plaît, ignorez ma réponse de 2015 car Javascript est maintenant compatible avec le
extends
mot-clé depuis ES6 (Ecmasctipt6)- ES6:
- ES7:
la source
new ParentClass()
avant d'écraser le constructeur, vous avez déjà exécuté le constructeur parent. Je ne pense pas que ce soit un comportement correct si vous me demandez ...Résumé:
Javascript utilise un mécanisme appelé héritage prototypique . L'héritage prototypique est utilisé lors de la recherche d'une propriété sur un objet. Lorsque nous étendons des propriétés en javascript, nous héritons de ces propriétés d'un objet réel. Cela fonctionne de la manière suivante:
myObj.foo
oumyObj['foo']
) le moteur JS recherchera d'abord cette propriété sur l'objet lui-mêmeLorsque nous voulons étendre un objet en javascript, nous pouvons simplement lier cet objet dans la chaîne de prototypes. Il existe de nombreuses façons d'y parvenir, je décrirai 2 méthodes couramment utilisées.
Exemples:
1.
Object.create()
Object.create()
est une fonction qui prend un objet comme argument et crée un nouvel objet. L'objet qui a été passé en argument sera le prototype de l'objet nouvellement créé. Par exemple:2. Définition explicite de la propriété prototype
Lors de la création d'objets à l'aide de fonctions de constructeur, nous pouvons définir des propriétés d'ajout à sa propriété d'objet prototype. Les objets créés forment une fonction de constructeur lors de l'utilisation du
new
mot - clé, ont leur prototype défini sur le prototype de la fonction de constructeur. Par exemple:la source
Vous pouvez simplement le faire en utilisant:
Ensuite, utilisez-le comme:
Ce bien aboutit à:
la source
S'IL VOUS PLAÎT AJOUTER LA RAISON DU DOWNVOTE
Pas besoin d'utiliser une bibliothèque externe pour étendre
En JavaScript, tout est un objet (à l'exception des trois types de données primitifs, et même ils sont automatiquement enveloppés d'objets en cas de besoin). De plus, tous les objets sont mutables.
grâce à ross harmes, dustin diaz
la source
Cela permettra d'étendre vos propriétés à créer un nouvel objet avec les prototypes de paramètre d'objet sans modifier l'objet passé.
Mais si vous souhaitez étendre votre Object sans modifier ses paramètres, vous pouvez ajouter extendProperty à votre objet.
la source
Le prototypage est un bon moyen, mais le prototype est parfois assez dangereux et peut conduire à des bugs. Je préfère encapsuler ceci dans un objet de base, comme Ember.js le fait pour Ember.Object.extend et Ember.Object.reopen. C'est beaucoup plus sûr à utiliser.
J'ai créé un aperçu de la façon dont vous configureriez quelque chose de similaire à ce qu'utilise Ember.Object.
Voici le lien: https://gist.github.com/WebCloud/cbfe2d848c80d4b9e9bd
la source
Prototyping is a nice way, but prototype is quite dangerous sometimes and can lead to bugs.
Que veux-tu dire par là? L'utilisation de la chaîne de prototypes en JavaScript peut entraîner des bogues? C'est comme dire que l'utilisation de classes sur Java peut conduire à des bogues et n'a absolument aucun sens.Object
le prototype de, votre fonction pourrait avoir le même nom qu'une future fonction JavaScript et provoquer l'explosion de votre code lors de son exécution future. Par exemple, disons que vous avez ajouté unerepeat()
fonctionObject
et l' avez appelée sur desString
instances, puis votre environnement d'exécution JavaScript mis à jour vers ES6?prototype
fonctionnalité du langage .