La première différence peut être résumée comme suit: this
fait référence à l' instance de la classe. prototype
fait référence à la définition .
Disons que nous avons la classe suivante:
var Flight = function ( number ) { this.number = number; };
Donc, ici, nous nous attachons this.number
à chaque instance de la classe, et cela a du sens car chacun Flight
devrait avoir son propre numéro de vol.
var flightOne = new Flight( "ABC" );
var flightTwo = new Flight( "XYZ" );
En revanche, prototype
définit une propriété unique accessible à toutes les instances.
Maintenant, si nous voulons obtenir le numéro de vol, nous pouvons simplement écrire l'extrait de code suivant et toutes nos instances obtiendront une référence à ce nouvel objet prototypé.
Flight.prototype.getNumber = function () { return this.number; };
La deuxième différence concerne la façon dont JavaScript recherche une propriété d'un objet. Lorsque vous recherchez Object.whatever
, JavaScript va jusqu'à l' objet Object principal (l'objet dont tout le reste a hérité), et dès qu'il trouvera une correspondance, il retournera ou l'appellera.
Mais cela ne se produit que pour les propriétés prototypées. Donc, si vous avez quelque part dans les niveaux supérieurs this.whatever
, JavaScript ne le considérera pas comme une correspondance et poursuivra la recherche.
Voyons comment cela se passe en réalité.
Notez d'abord que [presque] tout est des objets en JavaScript. Essaye ça:
typeof null
Voyons maintenant ce qu'il y a à l'intérieur Object
(notez les majuscules O
et .
à la fin). Dans les outils de développement de Google Chrome, lorsque vous entrez, .
vous obtiendrez une liste des propriétés disponibles à l'intérieur de cet objet spécifique.
Object.
Faites maintenant la même chose pour Function
:
Function.
Vous remarquerez peut-être la name
méthode. Allez-y et lancez-le et voyons ce qui se passe:
Object.name
Function.name
Créons maintenant une fonction:
var myFunc = function () {};
Et voyons si nous avons aussi la name
méthode ici:
myFunc.name
Vous devriez obtenir une chaîne vide, mais ça va. Vous ne devriez pas obtenir d'erreur ou d'exception.
Maintenant, ajoutons quelque chose à ce dieu Object
et voyons si nous l'obtenons également dans d'autres endroits?
Object.prototype.test = "Okay!";
Et voilà:
Object.prototype.test
Function.prototype.test
myFunc.prototype.test
Dans tous les cas, vous devriez voir "Okay!"
.
En ce qui concerne les avantages et les inconvénients de chaque méthode, vous pouvez considérer le prototypage comme une manière "plus efficace" de faire les choses, car il conserve une référence sur chaque instance plutôt que de copier la propriété entière dans chaque objet. D'un autre côté, c'est un exemple de couplage serré qui est un gros non jusqu'à ce que vous puissiez vraiment justifier la raison. this
est beaucoup plus compliqué car il est pertinent pour le contexte. Vous pouvez trouver de nombreuses bonnes ressources gratuitement sur Internet.
Cela dit, les deux méthodes ne sont que des outils linguistiques et cela dépend vraiment de vous et du problème que vous essayez de résoudre pour choisir ce qui vous convient le mieux.
Si vous avez besoin d'une propriété pour qu'elle soit pertinente pour chaque instance d'une classe, utilisez-la this
. Si vous avez besoin d'une propriété pour qu'elle fonctionne de la même manière sur chaque instance, utilisez-la prototype
.
Mise à jour
En ce qui concerne vos exemples d'extraits, le premier est un exemple de Singleton , il est donc judicieux d'utiliser this
dans le corps de l'objet. Vous pouvez également améliorer votre exemple en le rendant modulaire comme celui-ci (et vous n'avez pas besoin de toujours l'utiliser this
également).
/* Assuming it will run in a web browser */
(function (window) {
window.myApp = {
...
}
})( window );
/* And in other pages ... */
(function (myApp) {
myApp.Module = {
...
}
})( myApp );
/* And if you prefer Encapsulation */
(function (myApp) {
myApp.Module = {
"foo": "Foo",
"bar": function ( string ) {
return string;
},
return {
"foor": foo,
"bar": bar
}
}
})( myApp );
Votre deuxième extrait n'a pas beaucoup de sens, car vous utilisez d'abord this
et ensuite vous essayez de le pirater prototype
, ce qui ne fonctionne pas, car il this
est prioritaire prototype
. Je ne sais pas quelles étaient vos attentes par rapport à ce morceau de code et comment il fonctionnait, mais je vous recommande fortement de le refactoriser.
Mise à jour
Pour élaborer sur la this
priorité, prototype
je peux vous montrer un exemple et vous expliquer comment l'expliquer, mais je n'ai aucune ressource externe pour le sauvegarder.
L'exemple est très simple:
var myClass = function () { this.foo = "Foo"; };
myClass.prototype.foo = "nice try!";
myClass.prototype.bar = "Bar";
var obj = new myClass;
obj.foo; // Still contains "Foo" ...
obj.bar; // Contains "Bar" as expected
L'explication est, comme nous le savons, this
pertinente pour le contexte. Il n'existera donc que lorsque le contexte sera prêt. Quand le contexte est prêt? Lorsque la nouvelle instance est créée! Vous devriez deviner le reste maintenant! Cela signifie que même s'il existe une prototype
définition, il this
est plus logique de prendre la priorité, car il s'agit de la nouvelle instance créée à ce moment.