前面我们知道JS是基于对象编程的一种脚本语言,在JS本着一切皆对象的原则,对象之间也涉及到了继承,不过这里的继承与我们以往学习过的继承有所不同,它运用的是对象的原型,来构造一个原型链来实现对超类对象的继承。
1、如何实现对象继承
function Box() { //Box 构造<span style="font-family:Arial;font-size:18px;">,超类对象</span> this.name = 'Lee'; } Desk.prototype = new Box(); //<span style="font-family:Arial;font-size:18px;">子类继承</span>Desk,继承了 Box,通过原型,形成链条
继承原理小结:
1、通过原型链继承:超类型实例化后的对象实例赋给子类对象的原型属性。
2、new Box()会将超类对象构造函数和原型中的信息都交给子类对象,即继承全部信息 。
3、利用instanceof来判断子类是否从属于某个超类。
4、子类继承时,优先选择实例中的属性值(如果出现原型与构造实例冲突时)。
2、继承中的问题
上篇博客中还有一个遗留问题,原型函数共享带来无法重写的问题,那么在继承中,同样因为共享而无法进行重写,同时,子类无法给超类进行传参。对于这个问题,JS中可采用对象冒充来解决。
function Box(age) { this.name = ['Lee', 'Jack', 'Hello'] this.age = age; } function Desk(age) { Box.call(this, age); //对象冒充,给超类型传参 } var desk = new Desk(200); alert(desk.age);对象冒充SWOT分析:
1、实现了子类为超类对象进行传参问题
2、只能冒充构造函数中信息,不能冒充原型中的信息
当然,我们可以将所有信息写进构造函数中,但这样消耗内存空间太大,所以,这里可以采用原型链+构造函数的方式来实现,即组合模式:
function Box(age) { this.name = ['Lee', 'Jack', 'Hello'] this.age = age; } Box.prototype.run = function () { <span style="font-family:Arial;">//将方法写进原型中</span> return this.name + this.age; }; function Desk(age) { Box.call(this, age); //对象冒充,实现传参,第二次调用 } Desk.prototype = new Box(); //原型链继承,继承全部信息,第一次<span style="font-family:Arial;">调用</span>超类型 var desk = new Desk(100); alert(desk.run());
同时,还可以利用原型式继承等方法来实现对象传参问题,只需一个中转函数来协助返回一个实例化后的对象即可。
function obj(o) { //传递一个字面量函数 function F() {} //创建一个构造函数 F.prototype = o; //把字面量函数赋值给构造函数的原型 return new F(); //最终返回出实例化的构造函数 } var box = { //字面量对象 name : 'Lee', arr : ['哥哥','妹妹','姐姐'] }; box1.name = 'Jack'; alert(box1.name);但是原型式继承中由于中转函数中构造函数采用原型链继承,因此会出现引用类型共享问题,所以,通常不采用此种方法。
综上:JS继承中通常可采用组合式继承来实现为超类传参和重写问题,有时,由于为了更好的封装,解决组合中二次调用超类型问题,也会采用寄生组合继承来实现,这里还需要一个中转和寄生函数来实现。这个还有待深入学习。。。