Le prototype est une partie des notes en JavaScript difficile à comprendre. Nous allons expliquer ici le prototype en JS à travers plusieurs points de connaissances clés. Veuillez consulter les détails ci-dessous pour un contenu spécifique.
1 modèle de conception de prototype
Vous pouvez utiliser clone() pour implémenter la méthode prototype dans .Net
L'idée principale de la méthode prototype est qu'il existe maintenant une classe A, et je souhaite créer une classe B. Cette classe est basée sur A et peut être étendue. Nous appelons le prototype de B A.
2 méthodes JavaScript peuvent être divisées en trois catégories :
une méthode de classe
b Méthode objet
c méthode prototype
Exemple :
function People(name) { this.name=name; //对象方法 this.Introduce=function(){ alert("My name is "+this.name); } } //类方法 People.Run=function(){ alert("I can run"); } //原型方法 People.prototype.IntroduceChinese=function(){ alert("我的名字是"+this.name); } //测试 var p1=new People("Windking"); p1.Introduce(); People.Run(); p1.IntroduceChinese();
3 méthodes obj1.func.call(obj)
Cela signifie traiter obj comme obj1 et appeler la méthode func
D'accord, résolvons les problèmes un par un :
Que signifie prototype ?
Chaque objet en JavaScript a un attribut prototype. L'explication de l'attribut prototype d'un objet en Javascript est la suivante : renvoyer une référence au prototype du type d'objet.
A.prototype = new B();
Comprendre le prototype ne doit pas être confondu avec l'héritage. Le prototype de A est une instance de B. On peut comprendre que A a cloné toutes les méthodes et propriétés de B. A peut utiliser les méthodes et propriétés de B. L'accent est ici mis sur le clonage plutôt que sur l'héritage. Cette situation peut se produire : le prototype de A est une instance de B, et le prototype de B est également une instance de A.
Regardons un exemple expérimental :
function baseClass() { this.showMsg = function() { alert("baseClass::showMsg"); } } function extendClass() { } extendClass.prototype = new baseClass(); var instance = new extendClass(); instance.showMsg(); // 显示baseClass::showMsg
Nous définissons d'abord la classe baseClass, puis nous définissons extendClass, mais nous prévoyons d'utiliser une instance de baseClass comme prototype, et la classe extendée à cloner contient également la méthode objet showMsg.
extendClass.prototype = new baseClass() peut être lu comme : extendClass est créé en clonant une instance de baseClass comme prototype.
Ensuite, il y aura une question, et si extendClass lui-même contenait une méthode avec le même nom que la méthode de baseClass ?
Ce qui suit est l'expérience étendue 2 :
function baseClass() { this.showMsg = function() { alert("baseClass::showMsg"); } } function extendClass() { this.showMsg =function () { alert("extendClass::showMsg"); } } extendClass.prototype = new baseClass(); var instance = new extendClass(); instance.showMsg();//显示extendClass::showMsg
Preuve expérimentale : lorsque la fonction est en cours d'exécution, elle recherchera d'abord la fonction dans l'ontologie. Si elle est trouvée, elle sera exécutée. Si elle ne peut pas être trouvée, elle recherchera la fonction dans le prototype. Ou on peut comprendre que le prototype ne clonera pas la fonction du même nom.
Ensuite il y aura une nouvelle question :
Que faire si je souhaite utiliser une instance de extendClass pour appeler la méthode objet showMsg de baseClass ?
La réponse est d'utiliser l'appel :
extendClass.prototype = new baseClass(); var instance = new extendClass(); var baseinstance = new baseClass(); baseinstance.showMsg.call(instance);//显示baseClass::showMsg
Le baseinstance.showMsg.call(instance); se lit ici comme "Appeler l'instance en tant que baseinstance et appeler sa méthode objet showMsg"
D'accord, quelqu'un ici peut demander, pourquoi ne pas utiliser baseClass.showMsg.call(instance);
C'est la différence entre les méthodes objet et les méthodes de classe. Ce que nous voulons appeler est la méthode objet de baseClass
Enfin, si vous comprenez clairement le code suivant, alors vous pouvez comprendre ce que dit cet article :
<script type="text/javascript"> function baseClass() { this.showMsg = function() { alert("baseClass::showMsg"); } this.baseShowMsg = function() { alert("baseClass::baseShowMsg"); } } baseClass.showMsg = function() { alert("baseClass::showMsg static"); } function extendClass() { this.showMsg =function () { alert("extendClass::showMsg"); } } extendClass.showMsg = function() { alert("extendClass::showMsg static") } extendClass.prototype = new baseClass(); var instance = new extendClass(); instance.showMsg(); //显示extendClass::showMsg instance.baseShowMsg(); //显示baseClass::baseShowMsg instance.showMsg(); //显示extendClass::showMsg baseClass.showMsg.call(instance);//显示baseClass::showMsg static var baseinstance = new baseClass(); baseinstance.showMsg.call(instance);//显示baseClass::showMsg </script>
ps : Explication des attributs du prototype js et méthodes courantes
Fonction : Prototype
Chaque constructeur possède un attribut appelé prototype (prototype, qui ne sera pas traduit ci-dessous, utiliser son texte original). Cet attribut est très utile pour déclarer des variables ou des fonctions communes pour une classe spécifique.
Définition du prototype
Vous n'avez pas besoin de déclarer explicitement un attribut de prototype car il existe dans chaque constructeur. Vous pouvez jeter un oeil à l'exemple suivant :
Exemple PT1
CODE :
function Test() { } alert(Test.prototype); // 输出 "Object"
Ajouter des attributs au prototype
Comme vous pouvez le voir ci-dessus, le prototype est un objet, vous pouvez donc lui ajouter des propriétés. Les propriétés que vous ajoutez au prototype deviendront des propriétés communes aux objets créés à l'aide de ce constructeur.
Par exemple, j'ai un type de données Fish ci-dessous, et je veux que tous les poissons aient ces attributs : livesIn="water" et price=20 ; pour y parvenir, je peux ajouter ces attributs au prototype du constructeur Fish.
Exemple PT2
CODE :
function Fish(name, color) { this.name=name; this.color=color; } Fish.prototype.livesIn="water"; Fish.prototype.price=20;
Faisons ensuite du poisson :
CODE :
var fish1=new Fish("mackarel", "gray"); var fish2=new Fish("goldfish", "orange"); var fish3=new Fish("salmon", "white");
Jetons un coup d'œil aux attributs du poisson :
CODE :
for (int i=1; i<=3; i++) { var fish=eval_r("fish"+i); // 我只是取得指向这条鱼的指针 alert(fish.name+","+fish.color+","+fish.livesIn+","+fish.price); }
Le résultat devrait être :
CODE :
"mackarel, gray, water, 20" "goldfish, orange, water, 20" "salmon, white water, 20"
你看到所有的鱼都有属性livesIn和price,我们甚至都没有为每一条不同的鱼特别声明这些属性。这时因为当一个对象被创建时,这个构造函数 将会把它的属性prototype赋给新对象的内部属性__proto__。这个__proto__被这个对象用来查找它的属性。
你也可以通过prototype来给所有对象添加共用的函数。这有一个好处:你不需要每次在构造一个对象的时候创建并初始化这个函数。为了解释这一点,让我们重新来看Example DT9并使用prototype来重写它:
用prototype给对象添加函数
Example PT3
CODE:
function Employee(name, salary) { this.name=name; this.salary=salary; } Employee.prototype.getSalary=function getSalaryFunction() { return this.salary; } Employee.prototype.addSalary=function addSalaryFunction(addition) { this.salary=this.salary+addition; }
我们可以象通常那样创建对象:
CODE:
var boss1=new Employee("Joan", 200000); var boss2=new Employee("Kim", 100000); var boss3=new Employee("Sam", 150000);
并验证它:
CODE:
alert(boss1.getSalary()); // 输出 200000 alert(boss2.getSalary()); // 输出 100000 alert(boss3.getSalary()); // 输出 150000
这里有一个图示来说明prototype是如何工作的。这个对象的每一个实例(boss1, boss2, boss3)都有一个内部属性叫做__proto__,这个属性指向了它的构造器(Employee)的属性prototype。当你执行 getSalary或者addSalary的时候,这个对象会在它的__proto__找到并执行这个代码。注意这点:这里并没有代码的复制(和 Example DT8的图表作一下对比)。