原型继承要点:
一、每创建一个函数,就会同时创建一个它的prototype对象,这个对象(原型)也会自动获得constructor属性,并指向原函数。
二、所有引用类型默认都继承自Object,而这个继承也是通过原型链实现的。
三、所有函数的默认原型都是Object的实例,因此默认原型都会包含一个内部指针__proto__,指向 Object.prototype。而Object.prototype的constructor属性指向Object。注:使用对象字面量表示法新建(实例化)一个对象时,等同于new Object(),例如 var a = { };其实例 a 的prototype属性指向Object的原型Object.prototype,而原型的constructor属性指向Object。
四、当用构造函数实例化对象时,实例中的内部指针(__proto__)仅指向原型,而不指向构造函数。
五、属性继承只在读取属性值的时候发生,而当写入属性值的时候不会发生。
原型链的问题:
1、包含引用类型值的原型属性会被所有实例共享,但基本类型不会。
2、在创建子类型的实例时,不能向超类型的构造函数中传递参数。
DEMO
//包含引用类型的原型属性会被所有实例共享,但基本类型不会。 function SuperType(){ this.supp = ['supP']; this.supq = 'supQ'; } function SubType(){} SubType.prototype = new SuperType(); var sub1 = new SubType(); sub1.supp.push('aaa'); sub1.supq = 'bbb'; var sub2 = new SubType(); console.log('sub2.supp: ' + sub2.supp); //sub2.supp: supP,aaa console.log('sub2.supq: ' + sub2.supq); //sub2.supq: supQ //下面这个更有意思 sub1.supp = [1, 2]; console.log('sub1.supp: ' + sub1.supp); //sub1.supp: 1,2 console.log('sub2.supp: ' + sub2.supp); //sub2.supp: supP,aaa //为什么会这样呢?因为sub1.supp = [1, 2]操作,是在sub1当前环境的变量对象中添加了一个属性supp, //并指向[1, 2]。而不是沿作用域链,修改原型对象中的supp属性。 //属性继承只在读取属性值的时候发生,而当写入属性的时候不会发生。 console.log('sub1.__proto__.supp: ' + sub1.__proto__.supp); //sub1.__proto__.supp: supP,aaa
参考书籍:
JavaScript高级程序设计
JavaScript权威指南