Home  >  Article  >  Web Front-end  >  Detailed explanation of the principle of Javascript prototype chain_javascript skills

Detailed explanation of the principle of Javascript prototype chain_javascript skills

WBOY
WBOYOriginal
2016-05-16 15:21:421412browse

This article analyzes the principle of Javascript prototype chain through examples. Share it with everyone for your reference, the details are as follows:

1. JavaScript prototype chain

ECMAScript describes the concept of prototype chain and uses prototype chain as the main method to implement inheritance. The basic idea is to use prototypes to let one reference type inherit the properties and methods of another reference type. In JavaScript, the __proto__ attribute is used to represent an object’s prototype chain. When looking up a property of an object, JavaScript walks up the prototype chain until it finds a property with a given name!

For example, we now have the following code:

Extend the Object class and add Clone and Extend methods

/*扩展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;
}

Define Person class

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

In JavaScript, the Object class is the parent class of all classes, so the Person class inherits from the Object class and inherits all the public properties and public methods of the Object class, including the newly added Clone and Extend methods of the Object class

You can use the following code to prove that the Person class indeed inherits the Object class

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

Run result:

Then the Person class inherits the Object class through Shenma method. It is inherited using the prototype (prototye) method:

/*定义一个Person类*/
function Person(_name,_age){
   this.name = _name;
   this.age = _age;
}
Person.prototype = new Object();//让Person类继承Object类

Since JavaScript stipulates that any class inherits from the Object class, so "Person.prototype = new Object();//Let the Person class inherit the Object class " Even if we don't write it, I guess the JavaScript engine It will also automatically add this sentence for us, or use "Person.prototype = Object.prototype;" to let the Person class inherit the Object class. "Person.prototype = new Object();", in fact, this is equivalent to the Object object being a prototype of Person, which is equivalent to copying the properties and methods of the Object object to the Person.

2. How the new operator works

Let’s take a look at this piece of code first:

Copy code The code is as follows:
var p = new Person("lonewolf",24);//Create A person named Lone Ao Canglang

A very simple piece of code, let’s take a look at what this new does? We can split the new process into the following three steps:

1.var p={}; Initialize an object p.

2. p.__proto__=Person.prototype;, set the __proto__ attribute of object p to Person.prototype

3.Person.call(p,"lonewolf",24); Call the constructor Person to initialize p.

The key lies in the second step, let’s prove it:

var p = new Person("孤傲苍狼",24);//创建一个人,名字是孤傲苍狼
alert("p.__proto__ === Person.prototype的结果是:"+(p.__proto__ === Person.prototype));

The result of running under Firefox is:

This code will return true. Explain that our step 2 is correct.

Note: The __proto__ attribute is only publicly accessible in Firefox or Chrome browsers. Therefore, other browsers based on the IE kernel will not return true.

So what is __proto__? Let’s talk briefly here. Each object will initialize an attribute inside it, which is __proto__. When we access the attribute of an object, if this attribute does not exist inside the object, then he will go to __proto__ to find the attribute, this __proto__ It will have its own __proto__, so I keep looking for it, which is what we usually call the concept of prototype chain.

According to the standard, __proto__ is not open to the public, which means it is a private attribute. The __proto__ attribute cannot be accessed under IE, but the Firefox engine exposes it and makes it a public attribute. We Can be accessed and set externally.

Okay, the concept is clear, let us take a look at the following code:

<script type="text/javascript">
    var Person = function () { };
    Person.prototype.Say = function () {
      alert("Person say");
    }
    var p = new Person();
    p.Say();
</script>

This code is very simple. Let’s see why p can access Person’s Say.

First of all

Copy code The code is as follows:
var p=new Person();

It can be concluded that

Copy code The code is as follows:
p.__proto__=Person.prototype

So when we call p.Say(), first of all, there is no Say attribute in p, so he needs to find it in his __proto__, which is Person.prototype, and we defined it above

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 p=new Programmer();

可以得出

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

而在上面我们指定了

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

我们来这样拆分,

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

那么:

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

由根据上面得到

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

范例:查找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程序设计有所帮助。

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn