javascript之原型继承
今天在图书馆搞了一个下午才算优点门道的原型继承问题。书上说有多种,我现在摘下几个比较连贯的方法,这样学习起来比较深刻。另外几种都是可以在这几种方法中看到影子,比较好理解,就没有摘录下来。
1.1 原型链
原型链是指一个构造函数的原型是另一个构造函数的实例,从而实现继承。
(1)原型中包含constructor指向构造函数;
(2)实例中包含[[prototype]]指向构造函数的原型;
(3)当前一个构造函数实例化后,即可继承后一个构造函数的属性与方法。
由于后一个构造函数的属性变成了前一个构造函数的原型,因此,在实际应用中会导致和原型创建对象同样的问题——改变一个实例的引用数据,其他所有实例都将发生改变。
另外,后一个构造函数无法传入引用类型的数据,因为,该构造函数中的属性即为前一个构造函数的原型,这同样是导致同样的问题。
1.2 借用构造函数
function SuperType(){ this.colors =['red', 'blue', 'green']; }; function SubType(){ //继承 SuperType SuperType.call(this); //此处同样可以使用apply方法 }; var instance1 = new SubType(); instance1.colors.push('black'); alert(instance1.colors); var instance2 = new SubType(); alert(instance2.colors);
当然,这样同样可以在call中实现向SuperType()中传递参数。
但是,这还是存在问题:所有的参数都在SubType函数中进行定义,那这种重用性就无从谈起了。
1.3 组合继承
结合原型链和借用构造函数的技术,从而发挥两者的长处得到。即将私有的属性放在构造函数中,将共享的属性放在原型中。
组合继承是当前最常用的方式。
组合式继承中需要两次调用超类,因此有人提出了寄生式继承。
1.4 寄生式继承
先定义一个实例,然后将实例传递给构造函数的原型,同时将其中的constructor重新指向构造函数,然后在实例化时,调用超类即可。代码如下:
//寄生式继承 function SuperType(name){ this.name = name; this.colors = ['red', 'blue', 'green']; }; SuperType.prototype.getSuperVal = function(){ alert(this.name) }; function SubType(name, age){ SuperType.call(this, name); this.age = age; }; function inheritFromSuper(SubType, SuperType){ SubType.prototype = Object.create(new SuperType()); SubType.prototype.constructor = SubType; }; inheritFromSuper(SubType, SuperType); SubType.prototype.getSubVal = function(){ alert(this.age); }; var instance1 = new SubType('A', 29); var instance2 = new SubType('B', 20); instance1.colors.push('black'); alert(instance1.colors); alert(instance2.colors);