Il s'agit d'un modèle d'objet très simple, basé sur un prototype, qui serait considéré comme un échantillon pendant l'explication, sans commentaire pour l'instant :
function Person(name){
this.name = name;
}
Person.prototype.getName = function(){
console.log(this.name);
}
var person = new Person("George");
Il y a quelques points cruciaux que nous devons prendre en compte avant de passer au concept du prototype.
1- Comment les fonctions JavaScript fonctionnent réellement :
Pour faire le premier pas, nous devons comprendre comment les fonctions JavaScript fonctionnent réellement, comme une fonction de classe en utilisant this
ou simplement comme une fonction normale avec ses arguments, ce qu'elle fait et ce qu'elle renvoie.
Disons que nous voulons créer un Person
modèle objet. mais dans cette étape, je vais essayer de faire exactement la même chose sans utiliser prototype
y new
mot-clé .
Donc, dans cette étape functions
, objects
y this
mot-clé, sont tout ce que nous avons.
La première question serait comment this
pourrait être utile sans utiliser le mot-clé new
mot-clé .
Donc pour répondre à cette question, disons que nous avons un objet vide, et deux fonctions comme :
var person = {};
function Person(name){ this.name = name; }
function getName(){
console.log(this.name);
}
et maintenant sans utiliser new
mot-clé comment nous pourrions utiliser ces fonctions. JavaScript a donc 3 façons différentes de le faire :
a. La première façon est d'appeler la fonction comme une fonction normale :
Person("George");
getName();//would print the "George" in the console
dans ce cas, il s'agit de l'objet contexte actuel, qui est généralement l'objet global window
dans le navigateur ou GLOBAL
en Node.js
. Cela signifie que nous aurions, window.name dans le navigateur ou GLOBAL.name dans Node.js, avec "George" comme valeur.
b. Nous pouvons joindre à un objet, comme ses propriétés
- Le moyen le plus simple pour ce faire est de modifier le fichier vide person
objet, comme :
person.Person = Person;
person.getName = getName;
de cette façon nous pouvons les appeler comme :
person.Person("George");
person.getName();// -->"George"
et maintenant le person
est comme un objet :
Object {Person: function, getName: function, name: "George"}
- L'autre façon d'attacher une propriété à un objet est d'utiliser le prototype
de cet objet qui peut être trouvé dans n'importe quel objet JavaScript portant le nom de __proto__
et j'ai essayé de l'expliquer un peu dans la partie résumé. Nous pourrions donc obtenir le même résultat en faisant :
person.__proto__.Person = Person;
person.__proto__.getName = getName;
Mais de cette façon, ce que nous faisons réellement c'est modifier le Object.prototype
car chaque fois que nous créons un objet JavaScript en utilisant des littéraux ( { ... }
), il est créé sur la base de Object.prototype
ce qui signifie qu'il est attaché à l'objet nouvellement créé comme un attribut nommé __proto__
Par conséquent, si nous le modifions, comme nous l'avons fait dans notre extrait de code précédent, tous les objets JavaScript seront modifiés, ce qui n'est pas une bonne pratique. Alors quelle pourrait être la meilleure pratique maintenant :
person.__proto__ = {
Person: Person,
getName: getName
};
et maintenant d'autres objets sont en paix, mais ça ne semble toujours pas être une bonne pratique. Nous avons donc encore une solution, mais pour l'utiliser, nous devons revenir à cette ligne de code où person
a été créé ( var person = {};
) puis changez-le comme suit :
var propertiesObject = {
Person: Person,
getName: getName
};
var person = Object.create(propertiesObject);
ce qu'il fait est de créer un nouveau JavaScript Object
et attachez le propertiesObject
au __proto__
attribut. Donc pour être sûr que vous pouvez le faire :
console.log(person.__proto__===propertiesObject); //true
Mais le point délicat ici est que vous avez accès à toutes les propriétés définies dans __proto__
au premier niveau de la person
(lire la partie résumé pour plus de détails).
comme vous le voyez en utilisant l'un de ces deux moyens this
indiquerait exactement le person
objet.
c. JavaScript a une autre façon de fournir la fonction avec this
qui utilise appelez o appliquer pour invoquer la fonction.
La méthode apply() appelle une fonction avec une valeur donnée et des arguments fournis sous la forme d'un tableau (ou d'un objet de type tableau). arguments fournis sous forme de tableau (ou d'un objet de type tableau).
y
La méthode call() appelle une fonction avec une valeur donnée et les arguments fournis individuellement.
de cette façon qui est ma préférée, nous pouvons facilement appeler nos fonctions comme :
Person.call(person, "George");
o
//apply is more useful when params count is not fixed
Person.apply(person, ["George"]);
getName.call(person);
getName.apply(person);
ces 3 méthodes sont les étapes initiales importantes pour comprendre la fonctionnalité du .prototype.
2- Comment le new
le travail sur les mots-clés ?
c'est la deuxième étape pour comprendre le .prototype
fonctionnalité.C'est ce que j'utilise pour simuler le processus :
function Person(name){ this.name = name; }
my_person_prototype = { getName: function(){ console.log(this.name); } };
dans cette partie, je vais essayer de suivre toutes les étapes de JavaScript, sans utiliser la fonction new
mot-clé et prototype
lorsque vous utilisez new
mot-clé. donc quand on fait new Person("George")
, Person
sert de constructeur. Voici ce que fait JavaScript, un par un :
a. Tout d'abord, il crée un objet vide, en fait un hash vide :
var newObject = {};
b. la prochaine étape que JavaScript prend est de joindre tous les objets prototypes à l'objet nouvellement créé
nous avons my_person_prototype
ici similaire à l'objet prototype.
for(var key in my_person_prototype){
newObject[key] = my_person_prototype[key];
}
Ce n'est pas la façon dont JavaScript attache les propriétés qui sont définies dans le prototype. La manière réelle est liée au concept de chaîne de prototypes.
a. & b. Au lieu de ces deux étapes, vous pouvez obtenir exactement le même résultat en faisant :
var newObject = Object.create(my_person_prototype);
//here you can check out the __proto__ attribute
console.log(newObject.__proto__ === my_person_prototype); //true
//and also check if you have access to your desired properties
console.log(typeof newObject.getName);//"function"
maintenant nous pouvons appeler le getName
dans notre my_person_prototype
:
newObject.getName();
c. puis il donne cet objet au constructeur,
nous pouvons le faire avec notre échantillon comme :
Person.call(newObject, "George");
o
Person.apply(newObject, ["George"]);
alors le constructeur peut faire ce qu'il veut, parce que este à l'intérieur de ce constructeur est l'objet qui vient d'être créé.
maintenant le résultat final avant de simuler les autres étapes : Objet {nom : "George"}
Résumé :
Fondamentalement, lorsque vous utilisez le nouveau sur une fonction, vous faites appel à celle-ci et cette fonction sert de constructeur, donc quand vous dites :
new FunctionName()
JavaScript crée en interne un objet, un hash vide, puis il donne cet objet au constructeur, qui peut alors faire ce qu'il veut, car este à l'intérieur de ce constructeur est l'objet qui vient d'être créé et ensuite il vous donne cet objet bien sûr si vous n'avez pas utilisé l'instruction de retour dans votre fonction ou si vous avez mis un return undefined;
à la fin du corps de votre fonction.
Ainsi, lorsque JavaScript cherche une propriété sur un objet, la première chose qu'il fait est de la chercher sur cet objet. Et puis il y a une propriété secrète [[prototype]]
que nous avons habituellement comme __proto__
et cette propriété est ce que JavaScript regarde ensuite. Et quand il regarde dans le __proto__
Dans la mesure où il s'agit à nouveau d'un autre objet JavaScript, il possède sa propre fonction __proto__
attribut, il monte et monte jusqu'à ce qu'il arrive au point où le prochain __proto__
est nulle. Le point est le seul objet en JavaScript dont la fonction __proto__
est nul est Object.prototype
objet :
console.log(Object.prototype.__proto__===null);//true
et c'est ainsi que l'héritage fonctionne en JavaScript.
En d'autres termes, lorsque vous avez une propriété prototype sur une fonction et que vous appelez un new sur cette fonction, après que JavaScript ait fini de rechercher les propriétés de l'objet nouvellement créé, il va regarder le fichier .prototype
et il est également possible que cet objet ait son propre prototype interne. et ainsi de suite.
83 votes
John Resig a quelques diapositives sur les prototypes de fonction qui m'ont été utiles lorsque j'ai étudié le sujet (vous pouvez également apporter des modifications au code et voir ce qui se passe...) http://ejohn.org/apps/learn/#64
5 votes
Super matériel de référence, dans le but de maintenir cette question informative, placez peut-être quelques commentaires du site de John sur votre réponse au cas où son site serait modifié de manière à ce que votre lien ne soit plus disponible. De toute façon +1, cela m'a aidé.
96 votes
+1 pour votre lien vers diapositive Ninja JavaScript de John Resig #64. À partir de là, cela a vraiment été utile, et j'ai l'impression de bien comprendre les prototypes.
4 votes
Avons-nous vraiment besoin d'un objet fonctionnel pour appliquer un prototype ? si oui, pourquoi ?
6 votes
Cela pourrait vous aider : webdeveasy.com/javascript-prototype
1 votes
J'ai écrit quelque chose qui, je l'espère, est assez clair: La propriété prototype de JavaScript
0 votes
Une introduction au prototype en JavaScript
0 votes
Un autre lien utile: adamscheller.com/prototypes-in-javascript-tutorial
1 votes
Beaucoup de confusion (du moins pour moi) vient du sens quelque peu ambigu de "le prototype d'une fonction constructeur" : cela peut signifier soit constructor.prototype or constructor.__proto__. Assurez-vous de bien comprendre les deux
0 votes
N'oubliez pas un point-virgule ; après une déclaration ;-)