js 原型链

掌握 js 原型链,对理解 js 的指向有很大帮助,以下通过一个例子进行简单说明

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Document</title>
 6     <script>
 7         function Person( user ){
 8             this.userName = user;
 9         };
10         Person.prototype.showUserName = function(){
11             return this.userName;
12         };
13 
14         var obj = new Object();
15         obj.userName = "huanying2015";
16         Person.prototype = obj;
17 
18         var OP1 = new Person('zhangsan');
19         // 结果分析:实例化一个对象OP1,传入参数"zhangsan",调用构造函数Person,把this.userName设置为"zhangsan",所以输出结果为"zhangsan"
20         console.log( OP1.userName );                            // zhangsan
21         delete OP1.userName;       
22         // 因为在第21行删除了OP1的 userName 属性,所以输出OP1,结果为空对象    
23         console.log( OP1 );                                     // Person {}
24         // 因为在第16行改变了Person.prototype 的指向,所以此时Person.prototype 指向obj; OP1上没有userName属性,就往上查找原型链,最终找到obj上的userName 属性,所以输出huanying2015
25         console.log( OP1.userName );                            //  huanying2015 
26 
27         // OP1的隐式原型属性 __proto__ 指向 Person的原型对象即Person.prototype, 所以输出结果为 true
28         console.log( OP1.__proto__ === Person.prototype );      // true
29         // OP1.__proto__即是Person.prototype , 也就是obj(16行做的改变),相当于输出obj.userName ,所以结果为:huanying2015
30         console.log( OP1.__proto__.userName );                  //  huanying2015 
31         
32         var OP1 = new Person('wanger');
33         // 重新实例化一个OP1,传入参数为“wanger”,经过调用构造函数Person,所以得到一个新对象
34         console.log( OP1 );           // Person { userName:"wanger"}  
35 
36         // OP1的隐式原型属性 __proto__ 指向 Person的原型对象即Person.prototype, 原型对象并没有改变,所以输出结果为 true
37         console.log( OP1.__proto__ === Person.prototype );      // true
38         // Person 的原型对象并没有改变什么,所以输出结果为 Object
39         console.log( Person.prototype );  // Object {userName:"huanying2015"}
40 
41         // Person.prototype 的指向改变了(第16行),所以输出结果为false 
42         console.log( Person.prototype.constructor === Person  ); // falsse
43         // 实际上输出 Object(),因为指向在第 16 行改变了
44         console.log( Person.prototype.constructor );             // function Object() { [native code] }
45         // 在第16行指向改变了,所以原先在原型对象上的showUserName() 方法也就不存在了,调用不存在的方法,所以报错
46         OP1.showUserName();                                      //报错: Uncaught TypeError: OP1.showUserName is not a function
47 
48     </script>
49 </head>
50 <body>
51     
52 </body>
53 </html>

运行结果:

原型链说明:

/**************************************************************************************************************************************************

1. 任何一个函数,它的原型对象(prototype)上,都天生自带一个constructor 属性,这个属性指向函数的构造函数本身
2. 任何一个函数,都天生自带一个Prototype 属性,这个属性指向函数的原型对象
3. 任何一个对象(例如 :实例),都天生自带一个隐式原型__proto__属性,这个属性指向构造函数的原型对象(prototype)
4. 函数原型对象上的 隐式原型属性(__proto__)指向 Object对象
5. Object上的原型对象属性指向Object的原型对象(Object.prototype)
6. Object.prototype 上的隐式原型属性(__proto__)指向null

****************************************************************************************************************************************************/

原型链图解:

Person.prototype的指向改变之前

Person.prototype的指向改变之后:



http://www.cnblogs.com/huanying2015 博客随笔大多数文章均属原创,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利
原文地址:https://www.cnblogs.com/huanying2015/p/8052796.html