一、原型链
ECMAScript中将原型链作为实现继承的主要方法,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法.
实例1:
function SupType() { this.property = true; } SupType.prototype.getSupvalue = function() { return this.property; }; function SubType() { this.subproperty = false; } //原型对象等于一个类型的实例 SubType.prototype = new SupType(); SubType.prototype.getSubValue = function() { return this.subproperty; }; var instance = new SubType(); alert(instance.getSupvalue());//true
原理分析:
javascript中继承的原理是通过原型让一个引用类型继承另一个引用类型的属性和方法,当一个原型对象等于一个引用类型的实例(就如同将一个对象赋值给另一个对象一样,此时被赋值的对象就拥有了这个对象的属性或方法),此时这个原型对象就拥有了这个实例所拥有的属性或方法.
SupType的实例中包含一个指向原型对象的内部指针和一个属性property,SupType的实例被赋值给了SubType原型对象,现在SubType原型对象中就包含了指向SupType原型对象的内部指针和property属性.此时SubType的实例对象就可以访问到SupType构造函数中的方法getSupvalue,当前getSupvalue中的this指向的是SubType的实例对象,所以最后得到的结果为true.
理解javascript中的原型模式 ,理解了原型模式就很好理解javascript中的原型链,从而就很好理解JavaScript中的继承.
二、继承中定义方法的2个规则.
1.当子类型要重写超类型中的方法或是要为超类型添加不存在的方法时,给原型添加方法的代码必须放在替换原型的语句之后.
实例1:
function SupType() { this.property = true; } SupType.prototype.getSupvalue = function() { return this.property; }; function SubType() { this.subproperty = false; } //原型对象等于一个类型的实例 SubType.prototype = new SupType(); SubType.prototype.getSupvalue = function() { return false; }; SubType.prototype.getSubValue = function() { return this.subproperty; }; //SubType.prototype = new SupType(); var instance = new SubType(); alert(instance.getSupvalue());//false
子类型重写了超类型中的方法,因此会屏蔽原来的方法,最后返回的结果为false.
实例2:
如果将SubType.prototype = new SupType();这段替换原型的语句放在给原型添加方法的后面,上面最后得到的结果为true.
function SupType() { this.property = true; } SupType.prototype.getSupvalue = function() { return this.property; }; function SubType() { this.subproperty = false; } //原型对象等于一个类型的实例 //SubType.prototype = new SupType(); SubType.prototype.getSupvalue = function() { return false; }; SubType.prototype.getSubValue = function() { return this.subproperty; }; SubType.prototype = new SupType(); var instance = new SubType(); alert(instance.getSupvalue());//true alert(instance.getSubValue());// instance.getSubValue is not a function
如果是先给子类型的原型添加方法,然后再将超类型的实例赋值给子类型的原型,那么子类型的原型就被这个超类型的原型重写了,子类型中的方法都不再存在,现在子类型的原型指向的是超类型的原型对象,调用方法instance.getSupvalue()是超类型中的方法返回true.
2.通过原型链实现继承时,不要用字面量创建原型方法,这样会重写原型链.
实例:
function SupType() { this.property = true; } SupType.prototype.getSupvalue = function() { return this.property; }; function SubType() { this.subproperty = false; } //原型对象等于一个类型的实例 SubType.prototype = new SupType(); //SubType.prototype.getSupvalue = function() { // return false; //}; //SubType.prototype.getSubValue = function() { // return this.subproperty; //}; SubType.prototype = { getSubvalue: function() { return this.subproperty; } }; var instance = new SubType(); alert(instance.getSupvalue()); alert(instance.getSubValue());
测试结果:
重写原型链切断了子类型和超类型之间的关系(SubType和SupType现在没有了关系).