一、继承
继承,是指一个对象(子对象)通过某种方法,使得自己可以访问另一个对象(父对象)的属性和方法。而js没有提供继承的方法,所以我们可以自己通过原生方法来实现继承(实现继承的方法有很多,我们此次只讨论比较通用的一种)。其主要实现思路主要分为两步:
- 继承父对象的属性和方法。
- 继承父对象的原型。
1. 继承父对象的属性和方法
这一步要注意的是this的指向。在子构造函数里调用父构造函数,生成父对象的属性和方法之后,要能通过子对象访问,所以要改变this的引用。
function Super(a, b) {}
function Sub(a, b) {
Super.call(this, a, b);
}
// 或者写成
function Sub(a, b) {
this._super = Super; // 加个下划线是为了避免跟自己有的super属性冲突
this._super(); // 在this的那章我们讲过实际上等同于_super.call(this)
}
2. 继承父对象的原型
这一步要注意的是prototype和constructor的引用关系。不要直接Sub.prototype = Super.prototype
,因为这样赋值的是引用,在Sub.prototype
上的修改都会反过来影响Super.prototype
,所以要创建一个新的原型对象再赋值。另外一个是,修改原型后要相应的修改constructor,否则constructor会出现指向错误。
// 错误示例
Sub.prototype = Super.prototype;
console.log(Sub.prototype.constructor); // 返回的是Super,因为实例会继承原型的constructor从而覆盖自己本身的constructor
Sub.prototype.getAttr = function() {
return 'subAttr';
}
console.log(Super.prototype.getAttr); // 因为Sub.prototype得到的是引用,和Super.prototype指向的是同个地方,所以在上面的修改两者都会同步
// 正确示例
Sub.prototype = Object.create(Super.prototype);
Sub.prototype.constructor = Sub;
或许有小伙伴会问,Sub.prototype = new Super()
可以不?如果用这样的办法确实可以继承父类的属性和方法,但是父类实例的属性和方法也被继承到子构造函数的原型上了。
3. 完整例子
function Person(name, age) {
this.name = name;
this.age = age;
}
function Man(name, age) {
Person.call(this, name, age);
}
Man.prototype = Object.create(Person.prototype);
Man.prototype.construcotr = Man;
二、多继承
多继承,就是一个对象同时继承多个对象。原理基本类似,主要增加了Object.assgin
以扩充原型链。直接上代码:
function Super1() {}
function Super2() {}
function Sub() {
Super1.call(this);
Super2.call(this);
}
Sub.prototype = Object.create(Super1.prototype);
Object.assign(Sub.prototype, Super2.prototype);
Sub.prototype.constructor = Sub;
网友评论