深入理解JavaScript的原型对象

来源:互联网 发布:淘宝达人如何发布帖子 编辑:程序博客网 时间:2024/05/18 09:12

深入理解JavaScript的原型对象

标签: javascriptprototype继承
 452人阅读 评论(0) 收藏 举报
 分类:

目录(?)[+]

上一篇文章(JavaScript对象创建模式http://blog.csdn.net/hongse_zxl/article/details/44595809)介绍了JavaScript的对象创建的模式,其中简单介绍了原型对象。

JavaScript的继承机制是基于原型,而不是类。因此要理解JavaScript的继承机制,需要更深入了解原型对象。

先区分一下基于原型的常见写法:

这3种写法prototype,getPrototypeOf和__proto__之间的不同:

C.prototype:用于引用new C()创建的对象的原型对象

Object.getPrototypeOf(obj):是获取obj对象的原型对象的标准方法

obj.__proto__:是获取obj对象的原型对象的非标准方法

示意代码:

[javascript] view plain copy
  1. function Person(name, age) {    
  2.     this.name = name;    
  3.     this.age = age;  
  4. }    
  5. Person.prototype.sayName = function(){    
  6.     alert(this.name);    
  7. }    
  8.     
  9. var p1 = new Person("Jack", 32);  
  10. var p2 = new Person("Zhang", 30);    
  11. p1.sayName();   //Jack    
  12. p2.sayName();   //Zhang    
  13.   
  14. Object.getPrototypeOf(p1) === Person.prototype    //true  
  15. Object.getPrototypeOf(p2) === Person.prototype    //true  
  16.   
  17. p1.__proto__ === Person.prototype  //true  
  18. p2.__proto__ === Person.prototype  //true  
上面都是自解释代码,一看就能明白。通过C.prototype形式,可以获得原型对象,为之添加属性或方法。ES5环境下通过Object.getPrototypeOf(obj)可以检查现有对象的原型。一些环境提供了非标准的方法检索对象的原型,即特殊的属性__proto__,可以在不支持Object.getPrototypeOf方法时作为权宜之计。

(尽可能用Object.getPrototypeOf,而不要用__proto__,详细原因可以参见《Effective JavaScript》的<Item 31: Prefer Object.getPrototypeOf to __proto__>,简单地说__proto__是非安全的)

如何实现继承呢?

通过原型链来模拟其他OO语言中的继承。先回顾一下上一篇文章中介绍过的构造函数和原型对象和实例对象间的关系:

每个构造函数内部均有一个prototype原型指针,指向该类型的原型对象C.prototype。原型对象C.prototype中包含一个回指向构造函数的指针constructor。这样就实现了构造函数和原型对象间的双向绑定。每个实例对象内部也包含一个指向原型对象C.prototype的指针。

现在用原型链来实现JavaScript的继承:

[javascript] view plain copy
  1. //定义父类Person,构造函数内有两个属性name和age,原型对象内定义了sayName方法    
  2. function Person(name, age) {   
  3.     this.name = name;   
  4.     this.age = age;  
  5. }   
  6. Person.prototype.sayName = function(){   
  7.     alert(this.name);   
  8. }  
  9.   
  10. //定义子类Man,让其模拟继承父类  
  11. Personfunction Man(name, age){   
  12.     Person.call(this, name, age);  //子类中调用父类的构造函数   
  13.     this.gender = "male";          //子类中定义个新属性gender  
  14. }  
  15.   
  16. Man.prototype = new Person();  //继承是通过创建父类的原型对象,并将子类的prototype指针指向该原型对象来实现的  
  17. Man.prototype.constructor = Person;  
  18. Man.prototype.sayGender = function (){   
  19.     alert(this.gender);   
  20. };  
  21.   
  22. var m1 = new Man("Jack", 32);  
  23. m1.sayName();    //Jack  
  24. m1.sayGender();  //male  
  25. var m2 = new Man("Zhang", 30);  
  26. m2.sayName();    //Zhang  
  27. m2.sayGender();  //male  
  28.   
  29. alert(m1 instanceof Object); //true,显然创建的实例对象,既是Object,也是Person,也是Man  
  30. alert(m1 instanceof Person); //true  
  31. alert(m1 instanceof Man);    //true  
  32.   
  33. alert(Object.prototype.isPrototypeOf(m1));  //true  
  34. alert(Person.prototype.isPrototypeOf(m1));  //true  
  35. alert(Man.prototype.isPrototypeOf(m1));     //true  
示意图:



0 0
原创粉丝点击