Maison > interface Web > js tutoriel > le corps du texte

Explication détaillée du principe du prototype Javascript chain_javascript skills

WBOY
Libérer: 2016-05-16 15:21:42
original
1412 Les gens l'ont consulté

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;
}

Copier après la connexion

Définir la classe Personne

/*定义一个Person类*/
 function Person(_name,_age){
   this.name = _name;
   this.age = _age;
}

Copier après la connexion

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("
");
Copier après la connexion

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类

Copier après la connexion

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 :

Copier le code Le code est le suivant :
var p = new Person("lonewolf",24);// Créer une personne nommée Lone Ao Canglang

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));

Copier après la connexion

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>

Copier après la connexion

Ce code est très simple. Voyons pourquoi p peut accéder à Person’s Say.

Tout d'abord

Copier le code Le code est le suivant :
var p=new Person();

On peut conclure que

Copier le code Le code est le suivant :
p.__proto__=Person.prototype

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");
};

Copier après la connexion

于是,就找到了这个方法。

接下来,让我们看个更复杂的。

<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>

Copier après la connexion

我们来做这样的推导:

复制代码 代码如下:
var p=new Programmer();

可以得出

复制代码 代码如下:
p.__proto__=Programmer.prototype;

而在上面我们指定了

复制代码 代码如下:
Programmer.prototype=new Person();

我们来这样拆分,

var p1=new Person();
Programmer.prototype=p1;

Copier après la connexion

那么:

p1.__proto__=Person.prototype;
Programmer.prototype.__proto__=Person.prototype;

Copier après la connexion

由根据上面得到

复制代码 代码如下:
p.__proto__=Programmer.prototype

可以得到:

复制代码 代码如下:
p.__proto__.__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;
}

Copier après la connexion

范例:查找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>

Copier après la connexion

在火狐下的运行结果:

其实prototype只是一个假象,他在实现原型链中只是起到了一个辅助作用,换句话说,他只是在new的时候有着一定的价值,而原型链的本质,其实在于__proto__。

希望本文所述对大家JavaScript程序设计有所帮助。

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!