Maison >interface Web >js tutoriel >Explication détaillée du principe du prototype Javascript chain_javascript skills
Cet article analyse le principe de la chaîne de prototypes Javascript à travers des exemples. Partagez-le avec tout le monde pour votre référence, les détails sont les suivants :
1. Chaîne de prototypes JavaScript
ECMAScript décrit le concept de chaîne de prototypes et utilise la chaîne de prototypes comme méthode principale pour implémenter l'héritage. L'idée de base est d'utiliser des prototypes pour permettre à un type référence d'hériter des propriétés et des méthodes d'un autre type référence. En JavaScript, l'attribut __proto__ est utilisé pour représenter la chaîne de prototypes d'un objet. Lors de la recherche d'une propriété d'un objet, JavaScript parcourt la chaîne de prototypes jusqu'à trouver une propriété portant un nom donné !
Par exemple, nous avons maintenant le code suivant :
Étendez la classe Object et ajoutez les méthodes Clone et Extend
/*扩展Object类,添加Clone,JS实现克隆的方法*/ Object.prototype.Clone = function(){ var objClone; if (this.constructor == Object){ objClone = new this.constructor(); }else{ objClone = new this.constructor(this.valueOf()); } for(var key in this){ if ( objClone[key] != this[key] ){ if ( typeof(this[key]) == 'object' ){ objClone[key] = this[key].Clone(); }else{ objClone[key] = this[key]; } } } objClone.toString = this.toString; objClone.valueOf = this.valueOf; return objClone; } /*扩展Object类,添加Extend方法来实现JS继承, 目标对象将拥有源对象的所有属性和方法*/ Object.prototype.Extend = function (objDestination, objSource) { for (var key in objSource) { if (objSource.hasOwnProperty(key) && objDestination[key] === undefined) { objDestination[key] = objSource[key]; } } return objDestination; }
Définir la classe Personne
/*定义一个Person类*/ function Person(_name,_age){ this.name = _name; this.age = _age; }
En JavaScript, la classe Object est la classe parent de toutes les classes, donc la classe Person hérite de la classe Object et hérite de toutes les propriétés publiques et méthodes publiques de la classe Object, y compris les nouvelles fonctions Clone et Extend. méthodes de la classe Object
Vous pouvez utiliser le code suivant pour prouver que la classe Person hérite bien de la classe Object
document.write("<pre class="brush:php;toolbar:false">"); var p = new Person("孤傲苍狼",24);//创建一个人,名字是孤傲苍狼 var cloneP = p.Clone();//p调用在Object类中定义的Clone方法来克隆自己,如果能得到一个cloneP,那就证明了Person类确实是继承了Object类,所以就拥有了Clone document.writeln("p是使用Person类以构造函数的方式创建出来的对象,p.name = "+p.name+",p.age = "+p.age); document.writeln("cloneP是p调用Clone方法克隆出来的对象,cloneP.name = "+cloneP.name+",cloneP.age = "+cloneP.age); document.writeln("cloneP对象和p对象是两个相互独立的对象,这两个对象的内存地址肯定是不相等,p == cloneP的结果是:"+(p == cloneP)); cloneP.name="白虎神皇";//修改cloneP的名字 document.writeln("cloneP的name被修改了,cloneP.name = "+cloneP.name); document.writeln("cloneP的name修改了,但是不影响到p,p.name = "+p.name); document.write("");
Résultat de l'exécution :
Ensuite, la classe Person hérite de la classe Object via la méthode Shenma. Elle est héritée en utilisant la méthode prototype (prototye) :
/*定义一个Person类*/ function Person(_name,_age){ this.name = _name; this.age = _age; } Person.prototype = new Object();//让Person类继承Object类
Puisque JavaScript stipule que toute classe hérite de la classe Object, donc "Person.prototype = new Object();//Laissez la classe Person hériter de la classe Object " Même si on n'écrit pas cela, je suppose que le moteur JavaScript ajoutera également automatiquement cette phrase pour nous, ou utilisera "Person.prototype = Object.prototype;" pour laisser la classe Person hériter de la classe Object. "Person.prototype = new Object();", en fait, cela équivaut à ce que l'objet Object soit un prototype de Person, ce qui équivaut à copier les propriétés et méthodes de l'objet Object vers l'objet Person .
2. Comment fonctionne le nouvel opérateur
Jetons d'abord un coup d'œil à ce morceau de code :
Un morceau de code très simple, voyons ce que fait ce nouveau ? Nous pouvons diviser le nouveau processus en trois étapes :
1.var p={}; Initialiser un objet p.
2. p.__proto__=Person.prototype;, définissez l'attribut __proto__ de l'objet p sur Person.prototype
3.Person.call(p,"lonewolf",24); Appelez le constructeur Person pour initialiser p.
La clé réside dans la deuxième étape, prouvons-le :
var p = new Person("孤傲苍狼",24);//创建一个人,名字是孤傲苍狼 alert("p.__proto__ === Person.prototype的结果是:"+(p.__proto__ === Person.prototype));
Le résultat de l'exécution sous Firefox est :
Ce code retournera vrai. Expliquez que notre étape 2 est correcte.
Remarque : L'attribut __proto__ n'est accessible publiquement que dans les navigateurs Firefox ou Chrome. Par conséquent, les autres navigateurs basés sur le noyau IE ne renverront pas true.
Alors, qu'est-ce que __proto__ ? Parlons brièvement ici. Chaque objet initialisera un attribut à l'intérieur, qui est __proto__ Lorsque nous accédons à l'attribut d'un objet, si cet attribut n'existe pas à l'intérieur de l'objet, alors il ira dans __proto__ pour trouver l'attribut, ce __proto__ Il aura le sien. __proto__, donc je continue de le chercher, c'est ce que l'on appelle habituellement le concept de chaîne de prototypes.
Selon la norme, __proto__ n'est pas ouvert au public, ce qui signifie qu'il s'agit d'un attribut privé. L'attribut __proto__ n'est pas accessible sous IE, mais le moteur Firefox l'expose et en fait un attribut public. et réglé à l'extérieur.
D'accord, le concept est clair, regardons le code suivant :
<script type="text/javascript"> var Person = function () { }; Person.prototype.Say = function () { alert("Person say"); } var p = new Person(); p.Say(); </script>
Ce code est très simple. Voyons pourquoi p peut accéder à Person’s Say.
Tout d'abord
On peut conclure que
Donc, quand on appelle p.Say(), tout d'abord, il n'y a pas d'attribut Say dans p, il doit donc le trouver dans son __proto__, qui est Person.prototype, et nous l'avons défini ci-dessus
Person.prototype.Say=function(){ alert("Person say"); };
于是,就找到了这个方法。
接下来,让我们看个更复杂的。
<script type="text/javascript"> var Person = function () { }; Person.prototype.Say = function () { alert("Person say"); } Person.prototype.Salary = 50000; var Programmer = function () { }; Programmer.prototype = new Person();//让程序员类从人这个类继承 Programmer.prototype.WriteCode = function () { alert("programmer writes code"); }; Programmer.prototype.Salary = 500; var p = new Programmer(); p.Say(); p.WriteCode(); alert(p.Salary); </script>
我们来做这样的推导:
可以得出
而在上面我们指定了
我们来这样拆分,
var p1=new Person(); Programmer.prototype=p1;
那么:
p1.__proto__=Person.prototype; Programmer.prototype.__proto__=Person.prototype;
由根据上面得到
可以得到:
好,算清楚了之后我们来看上面的结果,p.Say()。由于p没有Say这个属性,于是去 p.__proto__,也就是Programmer.prototype,也就是p1中去找,由于p1中也没有Say,那就去 p.__proto__.__proto__,也就是Person.prototype中去找,于是就找到了Say方法。这也就是原型链的实现原理。
以下代码展示了JS引擎如何查找属性:
function getProperty(obj, prop) { if (obj.hasOwnProperty(prop)) return obj[prop]; else if (obj.__proto__ !== null) return getProperty(obj.__proto__, prop);//递归 else return undefined; }
范例:查找p对象的Say方法
<script type="text/javascript"> /*查找obj对象的prop属性*/ function getProperty(obj, prop) { if (obj.hasOwnProperty(prop)) return obj[prop]; else if (obj.__proto__ !== null) return getProperty(obj.__proto__, prop);//递归 else return undefined; } var Person = function () { };//定义Person类 Person.prototype.Say = function () { alert("Person say"); } Person.prototype.Salary = 50000; var Programmer = function () { };//定义Programmer类 //Programmer.prototype = new Person();//让程序员类从人这个类继承,写法一 Programmer.prototype = Person.prototype;//让程序员类从人这个类继承,写法二 Programmer.prototype.WriteCode = function () { alert("programmer writes code"); }; Programmer.prototype.Salary = 500; var p = new Programmer(); var SayFn = getProperty(p,"Say");//查找p对象的Say方法 SayFn.call(p);//调用找到的Say方法 </script>
在火狐下的运行结果:
其实prototype只是一个假象,他在实现原型链中只是起到了一个辅助作用,换句话说,他只是在new的时候有着一定的价值,而原型链的本质,其实在于__proto__。
希望本文所述对大家JavaScript程序设计有所帮助。