Quelle est la différence entre
var A = function () {
this.x = function () {
//do something
};
};
et
var A = function () { };
A.prototype.x = function () {
//do something
};
Les exemples ont des résultats très différents.
Avant d'examiner les différences, il convient de noter les points suivants:
[[Prototype]]
de l'instance.myObj.method()
), alors this dans la méthode fait référence à l'objet. Où this n'est pas défini par l'appel ni par l'utilisation de bind , il s'agit par défaut de l'objet global (fenêtre dans un navigateur ) ou en mode strict, reste indéfini.Alors voici les extraits en question:
var A = function () {
this.x = function () {
//do something
};
};
Dans ce cas, la variable A
reçoit une valeur qui fait référence à une fonction. Lorsque cette fonction est appelée à l'aide de A()
, la fonction this n'est pas définie par l'appel; elle est donc définie par défaut sur l'objet global et l'expression this.x
est efficace window.x
. Le résultat est qu'une référence à l'expression de fonction sur le côté droit est affectée à window.x
.
Dans le cas de:
var A = function () { };
A.prototype.x = function () {
//do something
};
quelque chose de très différent se produit. Dans la première ligne, la référence à une fonction est attribuée à la variable A
. En JavaScript, tous les objets de fonction ont par défaut une propriété prototype ; il n’existe donc pas de code distinct pour créer un objet A.prototype .
Dans la deuxième ligne, A.prototype.x se voit attribuer une référence à une fonction. Cela créera une propriété x si elle n'existe pas ou assignera une nouvelle valeur si elle existe. Ainsi, la différence avec le premier exemple dans lequel la propriété de l'objet x est impliquée dans l'expression.
Un autre exemple est ci-dessous. C'est semblable au premier (et peut-être ce que vous vouliez demander):
var A = new function () {
this.x = function () {
//do something
};
};
Dans cet exemple, l'opérateur new
a été ajouté avant l'expression de la fonction afin que celle-ci soit appelée en tant que constructeur. Lorsqu'elle est appelée avec new
, la fonction this est définie pour référencer un nouvel objet dont la propriété privée [[Prototype]]
est définie pour faire référence au public du constructeur prototype . Ainsi, dans l'instruction d'affectation, la propriété x
sera créée sur ce nouvel objet. Lorsqu'elle est appelée en tant que constructeur, une fonction retourne son objet this ==; il n'est donc pas nécessaire de disposer d'une instruction séparée return this;
.
Pour vérifier que A a une propriété x :
console.log(A.x) // function () {
// //do something
// };
Ceci est une utilisation peu commune de new == puisque le seul moyen de référencer le constructeur est via A.constructor . Il serait beaucoup plus courant de faire:
var A = function () {
this.x = function () {
//do something
};
};
var a = new A();
Un autre moyen d'obtenir un résultat similaire consiste à utiliser une expression de fonction immédiatement appelée:
var A = (function () {
this.x = function () {
//do something
};
}());
Dans ce cas, A
a attribué la valeur de retour de l'appel de la fonction à droite. Là encore, puisque this n'est pas défini dans l'appel, l'objet global sera référencé et this.x
sera effectif window.x
. Puisque la fonction ne renvoie rien, A
aura une valeur de undefined
.
Ces différences entre les deux approches se manifestent également si vous sérialisez et dé-sérialisez vos objets Javascript vers/à partir de JSON. Les méthodes définies sur le prototype d'un objet ne sont pas sérialisées lorsque vous sérialisez l'objet, ce qui peut s'avérer pratique lorsque vous souhaitez, par exemple, sérialiser uniquement les parties de données d'un objet, mais pas ses méthodes:
var A = function () {
this.objectsOwnProperties = "are serialized";
};
A.prototype.prototypeProperties = "are NOT serialized";
var instance = new A();
console.log(instance.prototypeProperties); // "are NOT serialized"
console.log(JSON.stringify(instance));
// {"objectsOwnProperties":"are serialized"}
Questions connexes :
Note: Il peut ne pas y avoir d'économie de mémoire significative entre les deux approches, mais l'utilisation du prototype pour partager des méthodes et des propriétés utilisera probablement moins de mémoire que chaque instance. avoir sa propre copie.
JavaScript n'est pas un langage de bas niveau. Il n’est peut-être pas très utile de penser au prototypage ou à d’autres modèles d’héritage pour modifier explicitement l’allocation de la mémoire.
Comme d'autres l'ont dit dans la première version, l'utilisation de "this" a pour résultat que chaque instance de la classe A possède sa propre copie indépendante de la méthode de fonction "x". Considérant que l'utilisation de "prototype" signifiera que chaque instance de classe A utilisera la même copie de la méthode "x".
Voici du code pour montrer cette différence subtile:
// x is a method assigned to the object using "this"
var A = function () {
this.x = function () { alert('A'); };
};
A.prototype.updateX = function( value ) {
this.x = function() { alert( value ); }
};
var a1 = new A();
var a2 = new A();
a1.x(); // Displays 'A'
a2.x(); // Also displays 'A'
a1.updateX('Z');
a1.x(); // Displays 'Z'
a2.x(); // Still displays 'A'
// Here x is a method assigned to the object using "prototype"
var B = function () { };
B.prototype.x = function () { alert('B'); };
B.prototype.updateX = function( value ) {
B.prototype.x = function() { alert( value ); }
}
var b1 = new B();
var b2 = new B();
b1.x(); // Displays 'B'
b2.x(); // Also displays 'B'
b1.updateX('Y');
b1.x(); // Displays 'Y'
b2.x(); // Also displays 'Y' because by using prototype we have changed it for all instances
Comme d'autres l'ont mentionné, il existe différentes raisons de choisir l'une ou l'autre méthode. Mon échantillon est juste destiné à démontrer clairement la différence.
Prenons ces 2 exemples:
var A = function() { this.hey = function() { alert('from A') } };
vs.
var A = function() {}
A.prototype.hey = function() { alert('from prototype') };
La plupart des gens ici (en particulier les réponses les mieux notées) ont essayé d'expliquer en quoi ils sont différents sans expliquer POURQUOI. Je pense que c'est faux et si vous comprenez d'abord les principes fondamentaux, la différence deviendra évidente. Essayons d'abord d'expliquer les principes fondamentaux ...
a) Une fonction est un objet en JavaScript. CHAQUE objet en JavaScript obtient une propriété interne (autrement dit, vous ne pouvez y accéder comme d’autres propriétés, sauf peut-être dans des navigateurs tels que Chrome), souvent appelé __proto__
(vous pouvez taper anyObject.__proto__
dans _.Chrome pour voir ce qu'il référence. C'est juste une propriété, rien de plus. Une propriété en JavaScript = une variable à l'intérieur d'un objet, rien de plus. Que font les variables? Elles pointent vers des choses.
Alors, qu'est-ce que cette propriété __proto__
pointe vers? Eh bien, généralement un autre objet (nous expliquerons pourquoi plus tard). Le seul moyen de forcer JavaScript pour que la propriété __proto__
ne pointe PAS vers un autre objet consiste à utiliser var newObj = Object.create(null)
. Même si vous faites cela, la propriété __proto__
STILL existe en tant que propriété de l'objet, mais elle ne pointe pas vers un autre objet, elle pointe sur null
.
Voici où la plupart des gens sont confus:
Lorsque vous créez une nouvelle fonction en JavaScript (qui est également un objet, n'oubliez pas?), Dès qu'elle est définie, JavaScript crée automatiquement une nouvelle propriété sur cette fonction appelée prototype
. Essayez le:
var A = [];
A.prototype // undefined
A = function() {}
A.prototype // {} // got created when function() {} was defined
A.prototype
est TOTALEMENT DIFFÉRENT de la propriété __proto__
. Dans notre exemple, 'A' a maintenant deux propriétés appelées 'prototype' et __proto__
. C'est une grande confusion pour les gens. Les propriétés prototype
et __proto__
ne sont aucunement liées, ce sont des éléments distincts pointant vers des valeurs distinctes.
Vous vous demandez peut-être pourquoi le code JavaScript a-t-il la propriété __proto__
créée sur chaque objet? Eh bien, un mot: délégation . Lorsque vous appelez une propriété sur un objet et que celui-ci ne l'a pas, JavaScript recherche l'objet qui est référencé par __proto__
pour voir s'il le possède peut-être. S'il ne l'a pas, alors il regarde la propriété __proto__
de cet objet et ainsi de suite ... jusqu'à la fin de la chaîne. Ainsi, le nom chaîne de prototypes . Bien sûr, si __proto__
ne pointe pas sur un objet mais sur null
, bonne chance, JavaScript le réalise et vous retournera undefined
pour la propriété.
Vous vous demandez peut-être également pourquoi JavaScript crée une propriété appelée prototype
pour une fonction lorsque vous définissez la fonction? Parce qu'il essaie de vous tromper, oui vous tromper qu'il fonctionne comme un langage basé sur les classes.
Continuons avec notre exemple et créons un "objet" à partir de A
:
var a1 = new A();
Il se passe quelque chose en arrière-plan quand c'est arrivé. a1
est une variable ordinaire à laquelle un nouvel objet vide a été attribué.
Le fait que vous ayez utilisé l'opérateur new
avant un appel de fonction A()
a effectué une opération ADDITIONAL en arrière-plan. Le mot clé new
a créé un nouvel objet, qui fait maintenant référence à a1
et cet objet est vide. Voici ce qui se passe en plus:
Nous avons dit que dans chaque définition de fonction, une nouvelle propriété créée appelée prototype
(à laquelle vous pouvez y accéder, contrairement à la propriété __proto__
) a été créée? Eh bien, cette propriété est utilisée maintenant.
Nous sommes donc maintenant au point où nous avons un objet vide a1
fraîchement cuit. Nous avons dit que tous les objets en JavaScript ont une propriété interne __proto__
qui pointe vers quelque chose (a1
l'a aussi), que ce soit null ou un autre objet. L’opérateur new
c’est qu’il définit cette propriété __proto__
pour qu'elle pointe sur la propriété prototype
de la fonction. Lisez cela à nouveau. C'est fondamentalement ceci:
a1.__proto__ = A.prototype;
Nous avons dit que A.prototype
n'est rien d'autre qu'un objet vide (à moins que nous ne le changions en autre chose avant de définir a1
). Donc maintenant, fondamentalement, a1.__proto__
pointe vers la même chose que A.prototype
pointe vers, qui est cet objet vide. Ils pointent tous deux vers le même objet qui a été créé lorsque cette ligne s'est produite:
A = function() {} // JS: cool. let's also create A.prototype pointing to empty {}
Maintenant, il se passe autre chose lorsque l'instruction var a1 = new A()
est traitée. Fondamentalement, A()
est exécuté et si A ressemble à ceci:
var A = function() { this.hey = function() { alert('from A') } };
Tout ce qui se trouve à l'intérieur de function() { }
va s'exécuter. Lorsque vous atteignez la ligne this.hey..
, this
devient a1
et vous obtenez ceci:
a1.hey = function() { alert('from A') }
Je ne couvrirai pas pourquoi this
change en a1
mais c'est une excellente réponse pour en savoir plus.
Donc, pour résumer, lorsque vous faites var a1 = new A()
, il se passe 3 choses en arrière-plan:
a1
. a1 = {}
La propriété a1.__proto__
est affectée à un point identique à celui de A.prototype
(un autre objet vide {})
La fonction A()
est en cours d'exécution avec this
sur le nouvel objet vide créé à l'étape 1 (lisez la réponse que j'ai citée plus haut pour expliquer pourquoi this
devient a1
)
Maintenant, essayons de créer un autre objet:
var a2 = new A();
Les étapes 1,2,3 se répètent. Avez-vous remarqué quelque chose? La clé Word est répétée . Étape 1: a2
sera un nouvel objet vide, étape 2: sa propriété __proto__
sera pointez sur la même chose que A.prototype
pointe sur et surtout, étape 3: la fonction A()
est AGAIN à nouveau exécutée, ce qui signifie que a2
obtiendra la propriété hey
contenant une fonction. a1
et a2
ont deux propriétés SEPARATE nommées hey
qui désignent 2 fonctions SEPARATE! Nous avons maintenant des fonctions en double dans deux objets différents faisant la même chose, oups ... Vous pouvez en imaginer les implications pour la mémoire si nous avons 1000 objets créés avec new A
, après que toutes les déclarations de fonctions utilisent plus de mémoire que quelque chose comme le nombre 2. Alors, comment pouvons-nous empêcher cela?
Rappelez-vous pourquoi la propriété __proto__
existe sur chaque objet? Ainsi, si vous récupérez la propriété yoMan
sur a1
(qui n'existe pas), sa propriété __proto__
sera consultée, ce qui sera le cas s'il s'agit d'un objet (et dans la plupart des cas). , il vérifiera s'il contient yoMan
, et s'il ne le fait pas, il consultera le __proto__
de cet objet, etc. Si tel est le cas, il prendra cette valeur de propriété et vous l'affichera.
Donc quelqu'un a décidé d'utiliser ce fait + le fait que lorsque vous créez a1
, sa propriété __proto__
pointe sur le même objet (vide) A.prototype
pointe sur et fait ceci:
var A = function() {}
A.prototype.hey = function() { alert('from prototype') };
Cool! Maintenant, lorsque vous créez a1
, il répète toutes les 3 étapes ci-dessus et à l'étape 3, il ne fait rien, car function A()
n'a rien à exécuter. Et si nous le faisons:
a1.hey
Il verra que a1
ne contient pas hey
et il vérifiera son objet de propriété __proto__
pour voir s'il en a un, ce qui est le cas.
Avec cette approche, nous éliminons la partie de l'étape 3 dans laquelle les fonctions sont dupliquées à chaque création d'objet. Au lieu de a1
et a2
ayant une propriété séparée hey
, AUCUN d'entre eux ne l'a maintenant. Ce qui, je suppose, vous l'avez compris vous-même. C'est la bonne chose ... si vous comprenez __proto__
et Function.prototype
, de telles questions seront assez évidentes.
REMARQUE: certaines personnes ont tendance à ne pas appeler la propriété interne Prototype sous le nom __proto__
. J'ai utilisé ce nom par le biais du message pour le distinguer clairement de la propriété Functional.prototype
de deux manières différentes.
Dans la plupart des cas, ils sont essentiellement identiques, mais la deuxième version économise de la mémoire car il n'existe qu'une seule instance de la fonction au lieu d'une fonction distincte pour chaque objet.
Une des raisons d'utiliser le premier formulaire est d'accéder aux "membres privés". Par exemple:
var A = function () {
var private_var = ...;
this.x = function () {
return private_var;
};
this.setX = function (new_x) {
private_var = new_x;
};
};
En raison des règles de portée de javascript, private_var est disponible pour la fonction attribuée à this.x, mais pas en dehors de l'objet.
Le premier exemple modifie l'interface pour cet objet uniquement. Le deuxième exemple modifie l'interface pour tous les objets de cette classe.
Le problème ultime lié à l'utilisation de this
au lieu de prototype
est que, lors du remplacement d'une méthode, le constructeur de la classe de base fera toujours référence à la méthode remplacée. Considère ceci:
BaseClass = function() {
var text = null;
this.setText = function(value) {
text = value + " BaseClass!";
};
this.getText = function() {
return text;
};
this.setText("Hello"); // This always calls BaseClass.setText()
};
SubClass = function() {
// setText is not overridden yet,
// so the constructor calls the superclass' method
BaseClass.call(this);
// Keeping a reference to the superclass' method
var super_setText = this.setText;
// Overriding
this.setText = function(value) {
super_setText.call(this, "SubClass says: " + value);
};
};
SubClass.prototype = new BaseClass();
var subClass = new SubClass();
console.log(subClass.getText()); // Hello BaseClass!
subClass.setText("Hello"); // setText is already overridden
console.log(subClass.getText()); // SubClass says: Hello BaseClass!
contre:
BaseClass = function() {
this.setText("Hello"); // This calls the overridden method
};
BaseClass.prototype.setText = function(value) {
this.text = value + " BaseClass!";
};
BaseClass.prototype.getText = function() {
return this.text;
};
SubClass = function() {
// setText is already overridden, so this works as expected
BaseClass.call(this);
};
SubClass.prototype = new BaseClass();
SubClass.prototype.setText = function(value) {
BaseClass.prototype.setText.call(this, "SubClass says: " + value);
};
var subClass = new SubClass();
console.log(subClass.getText()); // SubClass says: Hello BaseClass!
Si vous pensez que ce n'est pas un problème, cela dépend si vous pouvez vivre sans variables privées et si vous êtes suffisamment expérimenté pour connaître une fuite lorsque vous en voyez une. Aussi, avoir à mettre la logique du constructeur après les définitions de la méthode est peu pratique.
var A = function (param1) {
var privateVar = null; // Private variable
// Calling this.setPrivateVar(param1) here would be an error
this.setPrivateVar = function (value) {
privateVar = value;
console.log("setPrivateVar value set to: " + value);
// param1 is still here, possible memory leak
console.log("setPrivateVar has param1: " + param1);
};
// The constructor logic starts here possibly after
// many lines of code that define methods
this.setPrivateVar(param1); // This is valid
};
var a = new A(0);
// setPrivateVar value set to: 0
// setPrivateVar has param1: 0
a.setPrivateVar(1);
//setPrivateVar value set to: 1
//setPrivateVar has param1: 0
contre:
var A = function (param1) {
this.setPublicVar(param1); // This is valid
};
A.prototype.setPublicVar = function (value) {
this.publicVar = value; // No private variable
};
var a = new A(0);
a.setPublicVar(1);
console.log(a.publicVar); // 1
Chaque objet est lié à un objet prototype. Lorsque vous tentez d'accéder à une propriété qui n'existe pas, JavaScript recherchera cette propriété dans l'objet prototype de l'objet et la retournera s'il existe.
La propriété prototype
d'un constructeur de fonction fait référence à l'objet prototype de toutes les instances créées avec cette fonction lors de l'utilisation de new
.
Dans votre premier exemple, vous ajoutez une propriété x
à chaque instance créée avec la fonction A
.
var A = function () {
this.x = function () {
//do something
};
};
var a = new A(); // constructor function gets executed
// newly created object gets an 'x' property
// which is a function
a.x(); // and can be called like this
Dans le deuxième exemple, vous ajoutez une propriété à l'objet prototype sur laquelle toutes les instances créées avec A
.
var A = function () { };
A.prototype.x = function () {
//do something
};
var a = new A(); // constructor function gets executed
// which does nothing in this example
a.x(); // you are trying to access the 'x' property of an instance of 'A'
// which does not exist
// so JavaScript looks for that property in the prototype object
// that was defined using the 'prototype' property of the constructor
En conclusion, dans le premier exemple ne copie de la fonction est assignée à chaque instance. Dans le deuxième exemple ne seule copie de la fonction est partagée par toutes les instances.
Quelle est la différence? => Beaucoup.
Je pense que la version this
est utilisée pour activer l’encapsulation, c’est-à-dire le masquage de données. Cela aide à manipuler des variables privées.
Regardons l'exemple suivant:
var AdultPerson = function() {
var age;
this.setAge = function(val) {
// some Housekeeping
age = val >= 18 && val;
};
this.getAge = function() {
return age;
};
this.isValid = function() {
return !!age;
};
};
Maintenant, la structure prototype
peut être appliquée comme suit:
Différents adultes ont des âges différents, mais tous les adultes ont les mêmes droits.
Nous l’ajoutons donc en utilisant un prototype plutôt que celui-ci.
AdultPerson.prototype.getRights = function() {
// Should be valid
return this.isValid() && ['Booze', 'Drive'];
};
Regardons la mise en œuvre maintenant.
var p1 = new AdultPerson;
p1.setAge(12); // ( age = false )
console.log(p1.getRights()); // false ( Kid alert! )
p1.setAge(19); // ( age = 19 )
console.log(p1.getRights()); // ['Booze', 'Drive'] ( Welcome AdultPerson )
var p2 = new AdultPerson;
p2.setAge(45);
console.log(p2.getRights()); // The same getRights() method, *** not a new copy of it ***
J'espère que cela t'aides.
Le prototype est le modèle de la classe; qui s'applique à toutes les instances futures de celui-ci. Alors que c'est l'instance particulière de l'objet.
Laissez-moi vous donner une réponse plus complète que j'ai apprise lors d'un cours de formation sur JavaScript.
La plupart des réponses mentionnaient déjà la différence, c’est-à-dire que lors du prototypage, la fonction était partagée avec toutes les instances (futures). Tandis que déclarer la fonction dans la classe créera une copie pour chaque instance.
En général, il n’ya ni bon ni mauvais, c’est davantage une question de goût ou de décision de conception en fonction de vos besoins. Cependant, le prototype est la technique utilisée pour développer une approche orientée objet, comme j'espère que vous verrez à la fin de cette réponse.
Vous avez montré deux modèles dans votre question. Je vais essayer d’en expliquer deux autres et d’expliquer les différences, le cas échéant. N'hésitez pas à éditer/étendre. Dans tous les exemples, il s'agit d'un objet de voiture qui a un emplacement et peut se déplacer.
Vous ne savez pas si ce modèle est toujours d'actualité, mais il existe. Et il est bon de savoir à ce sujet. Vous passez simplement un objet et une propriété à la fonction décorateur. Le décorateur renvoie l'objet avec la propriété et la méthode.
var carlike = function(obj, loc) {
obj.loc = loc;
obj.move = function() {
obj.loc++;
};
return obj;
};
var amy = carlike({}, 1);
amy.move();
var ben = carlike({}, 9);
ben.move();
Une fonction en JavaScript est un objet spécialisé. En plus d'être appelée, une fonction peut stocker des propriétés comme n'importe quel autre objet.
Dans ce cas, Car
est un fonction (aussi think objet) qui peut être appelé comme vous le faites habituellement. Il a une propriété methods
(qui est un objet avec une fonction move
). Lorsque Car
est appelé, la fonction extend
est appelée, ce qui permet d'effectuer des opérations magiques et étend la fonction Car
(objet think) aux méthodes définies dans methods
.
Cet exemple, bien que différent, se rapproche le plus du premier exemple de la question.
var Car = function(loc) {
var obj = {loc: loc};
extend(obj, Car.methods);
return obj;
};
Car.methods = {
move : function() {
this.loc++;
}
};
var amy = Car(1);
amy.move();
var ben = Car(9);
ben.move();
Les deux premiers modèles permettent de discuter de l’utilisation de techniques pour définir des méthodes partagées ou de méthodes définies en ligne dans le corps du constructeur. Dans les deux cas, chaque instance a sa propre fonction move
.
Le modèle prototypal ne se prête pas bien au même examen, car le partage de fonctions via une délégation de prototype est l’objet même du modèle prototypal. Comme d'autres l'ont souligné, la mémoire devrait être meilleure.
Cependant, il y a un point intéressant à savoir: chaque objet prototype
a une propriété de commodité constructor
, qui renvoie à la fonction (objet de réflexion) à laquelle il est attaché.
Concernant les trois dernières lignes:
Dans cet exemple, Car
est lié à l'objet prototype
, qui relie via constructor
à Car
lui-même, c'est-à-dire Car.prototype.constructor
est Car
lui-même. Cela vous permet de déterminer quelle fonction de constructeur a construit un certain objet.
La recherche de amy.constructor
échoue et est donc déléguée à Car.prototype
, qui possède la propriété constructeur. Et ainsi amy.constructor
est Car
.
De plus, amy
est un instanceof
Car
. L'opérateur instanceof
fonctionne en vérifiant si l'objet prototype de l'opérande droit (Car
) peut être trouvé n'importe où dans la chaîne de prototypes de l'opérande gauche (amy
).
var Car = function(loc) {
var obj = Object.create(Car.prototype);
obj.loc = loc;
return obj;
};
Car.prototype.move = function() {
this.loc++;
};
var amy = Car(1);
amy.move();
var ben = Car(9);
ben.move();
console.log(Car.prototype.constructor);
console.log(amy.constructor);
console.log(amy instanceof Car);
Certains développeurs peuvent être confus au début. Voir ci-dessous exemple:
var Dog = function() {
return {legs: 4, bark: alert};
};
var fido = Dog();
console.log(fido instanceof Dog);
L'opérateur instanceof
renvoie false
, car le prototype de Dog
ne peut être trouvé nulle part dans la chaîne de prototypes de fido
. fido
est un objet simple créé avec un littéral d'objet, c'est-à-dire qu'il délègue simplement des délégués à Object.prototype
.
Il ne s’agit en réalité que d’une autre forme du motif prototype, simplifiée et plus familière pour ceux qui programment dans Java par exemple, car ils utilisent le constructeur new
.
Il fait la même chose que dans le modèle prototypal, c’est vraiment un sucre syntaxique par-dessus le modèle prototypal.
Cependant, la principale différence réside dans le fait que des optimisations implémentées dans les moteurs JavaScript ne s'appliquent que lors de l'utilisation du modèle pseudoclassique. Pensez que le motif pseudoclassique est une version probablement plus rapide du motif prototype; les relations d'objet dans les deux exemples sont les mêmes.
var Car = function(loc) {
this.loc = loc;
};
Car.prototype.move = function() {
this.loc++;
};
var amy = new Car(1);
amy.move();
var ben = new Car(9);
ben.move();
Enfin, il ne devrait pas être trop difficile de comprendre comment une programmation orientée objet peut être effectuée. Il y a deux sections.
Une section qui définit les propriétés/méthodes communes dans le prototype (chaîne).
Et une autre section où vous mettez les définitions qui distinguent les objets les uns des autres (loc
variable dans les exemples).
C'est ce qui nous permet d'appliquer des concepts tels que superclasse ou sous-classe en JavaScript.
N'hésitez pas à ajouter ou à modifier. Une fois de plus, je pourrais peut-être en faire un wiki de communauté.
Je sais que la réponse à cette question est mortelle, mais j'aimerais montrer un exemple concret de différence de vitesse.
Ici, nous créons 2 000 000 nouveaux objets avec une méthode print
dans Chrome. Nous stockons chaque objet dans un tableau. Mettre print
sur le prototype prend environ 1/2 fois plus longtemps.
Je crois que @Matthew Crumley a raison. Ils sont fonctionnellement , sinon structurellement, équivalents. Si vous utilisez Firebug pour examiner les objets créés à l'aide de new
, vous constatez qu'ils sont identiques. Cependant, ma préférence serait la suivante. J'imagine que cela ressemble plus à ce à quoi je suis habitué en C #/Java. Autrement dit, définissez la classe, définissez les champs, le constructeur et les méthodes.
var A = function() {};
A.prototype = {
_instance_var: 0,
initialize: function(v) { this._instance_var = v; },
x: function() { alert(this._instance_var); }
};
EDIT Ne voulait pas dire que la portée de la variable était privée, j'essayais simplement d'illustrer la façon dont je définis mes classes en javascript. Le nom de la variable a été modifié pour refléter cela.
Comme indiqué dans d'autres réponses, il s'agit en réalité d'une considération de performance, car la fonction du prototype est partagée avec toutes les instanciations - plutôt que la fonction créée pour chaque instanciation.
Je mets en place un jsperf pour le montrer. Il y a une différence considérable dans le temps nécessaire pour instancier la classe, bien que ce ne soit vraiment pertinent que si vous faites de nombreuses instances.
Pensez au langage de type statique, les choses sur prototype
sont statiques et les choses sur this
sont liées à des instances.