Il s'agit d'un modèle d'objet basé sur un prototype très simple qui serait considéré comme un échantillon lors de l'explication, sans aucun commentaire:
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 considérer avant de passer par le concept du prototype.
1- Comment fonctionnent réellement les fonctions JavaScript:
Pour prendre la première étape, nous devons comprendre comment les fonctions JavaScript fonctionnent réellement, en tant que fonction de classe utilisant un this
mot-clé ou simplement en tant que fonction régulière avec ses arguments, ce qu'elle fait et ce qu'elle retourne.
Disons que nous voulons créer un Person
modèle d'objet. mais dans cette étape, je vais essayer de faire exactement la même chose sans utiliser de mot prototype
- new
clé .
Donc, dans cette étape functions
, objects
et this
mot - clé, sont tout ce que nous avons.
La première question serait de savoir comment un this
mot clé pourrait être utile sans utiliser de new
mot clé .
Donc pour répondre à cela, 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 de new
mot-clé, comment nous pourrions utiliser ces fonctions. JavaScript a donc 3 façons différentes de le faire:
une. la première façon consiste simplement à appeler la fonction en tant que fonction régulière:
Person("George");
getName();//would print the "George" in the console
dans ce cas, ce serait l'objet de contexte actuel, qui est généralement le global window
objet dans le navigateur ou GLOBAL
dans 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 attacher à un objet, comme ses propriétés
- La façon la plus simple de le faire est de modifier l' person
objet vide , comme:
person.Person = Person;
person.getName = getName;
de cette façon, nous pouvons les appeler comme:
person.Person("George");
person.getName();// -->"George"
et maintenant l' person
objet est comme:
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 avec le nom de __proto__
, et j'ai essayé de l'expliquer un peu dans la partie récapitulative. Ainsi, nous pourrions obtenir le résultat similaire en faisant:
person.__proto__.Person = Person;
person.__proto__.getName = getName;
Mais de cette façon, ce que nous faisons est en train de modifier le Object.prototype
, car chaque fois que nous créons un objet JavaScript à l'aide de literals ( { ... }
), il est créé en fonction de Object.prototype
, ce qui signifie qu'il est attaché à l'objet nouvellement créé en tant qu'attribut nommé __proto__
, donc si nous le changeons , comme nous l'avons fait sur notre extrait de code précédent, tous les objets JavaScript seraient 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 cela ne semble toujours pas être une bonne pratique. Nous avons donc encore une solution, mais pour utiliser cette solution, nous devons revenir à cette ligne de code où l' person
objet a été créé ( var person = {};
), puis le changer comme:
var propertiesObject = {
Person: Person,
getName: getName
};
var person = Object.create(propertiesObject);
il crée un nouveau JavaScript Object
et attache le propertiesObject
à l' __proto__
attribut. Donc, pour vous assurer que vous pouvez 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 au __proto__
premier niveau de laperson
objet (lisez la partie récapitulative pour plus de détails).
comme vous le voyez en utilisant l'un de ces deux moyens this
pointerait exactement vers l' person
objet.
c. JavaScript a une autre façon de fournir la fonction this
, qui utilise l' appel ou l' application pour appeler 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).
et
La méthode call () appelle une fonction avec une valeur donnée et des 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");
ou
//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é .prototype.
2- Comment le new
mot clé?
c'est la deuxième étape pour comprendre la .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 que JavaScript prend, sans utiliser le new
mot - clé et prototype
, lorsque vous utilisez le new
mot-clé. donc quand nous le faisons new Person("George")
, la Person
fonction sert de constructeur, voici ce que fait JavaScript, un par un:
une. tout d'abord, il fait un objet vide, essentiellement un hachage vide comme:
var newObject = {};
b. l'étape suivante que JavaScript prend consiste à attacher 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 réellement les propriétés définies dans le prototype. La voie actuelle est liée au concept de chaîne prototype.
une. & b. Au lieu de ces deux étapes, vous pouvez obtenir exactement le même résultat en procédant comme suit:
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 la getName
fonction 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");
ou
Person.apply(newObject, ["George"]);
alors le constructeur peut faire ce qu'il veut, parce que 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: Object {name: "George"}
Sommaire:
Fondamentalement, lorsque vous utilisez le nouveau mot-clé sur une fonction, vous appelez cela et cette fonction sert de constructeur, donc quand vous dites:
new FunctionName()
JavaScript crée en interne un objet, un hachage vide, puis il donne cet objet au constructeur, puis le constructeur peut faire ce qu'il veut, car à 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 return dans votre fonction ou si vous avez mis un return undefined;
à la fin de votre corps de fonction.
Ainsi, lorsque JavaScript cherche une propriété sur un objet, la première chose qu'il fait, c'est qu'il la recherche 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 à travers __proto__
, tant qu'il s'agit encore d'un autre objet JavaScript, il a son propre __proto__
attribut, il monte et monte jusqu'à ce qu'il atteigne le point où le suivant __proto__
est nul. Le point est le seul objet en JavaScript dont l' __proto__
attribut est nul est un 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 en appelez une nouvelle, une fois que JavaScript a fini de regarder cet objet nouvellement créé pour les propriétés, il va regarder les fonctions .prototype
et il est également possible que cet objet ait son propre prototype interne. etc.