什么是继承
普通的继承:子女继承父辈的遗产、事业,后人继承祖先的传统、精神
编程语言:继承是面向对象语言的重要特性,继承是针对于类而言,(默认你知道类可以派生实例)子类继承父类,父类中的属性和方法,子类也会包含。见下:
爷爷类 交通工具: 能运输
父类 飞机(继承交通工具) 能运输 能飞 | 父类 汽车(继承交通工具) 能运输 能跑
子类 直升飞机 (继承飞机) 能运输 能飞 直上直下 |
子类 公交车 (继承汽车) 能运输 能跑 收费2元
不难看出继承可以由上自下层层实现,并且子类在保持父类的特性之外,都拥有自己独特的属性。
JavaScript中的继承
JavaScript也属于面向对象语言。与一般的面向对象语言有区别的是,JavaScript中没有类,直接通过函数直接派生实例,详见我的另一篇文章(ES6的class关键字也是通过函数实现 不信你试试 typeof 某class === 'function' / 某class instanceof Function)。
既然面向对象,何不实现继承?
JavaScript的继承方式:通过改变this来实现
(如果没有掌握this和原型链的知识,请参阅我的this以及原型链文章:)
function Person () {
this.head = 1;
this.shoulders = 2; //两个肩膀扛一个脑袋
}
//将可以复用的方法放入prototype中
Person.prototype.say = function () {
console.log('hello')
}
实例化:
let oneMan = new Person(); // { head:1, shoulders:2 }
oneMan.say() // hello
开始继承
子类,定义一个父亲,在函数体内调用Person:
function Father () {
Person.call(this)
this.gender = 'male' //性别男
}
调用了Call,Person中的this变成了Father的this,等价于:
function Father () {
this.head = 1;
this.shoulders = 2;
this.gender = 'male'
}
此时Father也是俩肩膀扛一个脑袋了,并且多了一个性别:
let dad = new Father() // { head:1, shoulders:2, gender:'male' }
然而现在Father不会说话,因为并没有把Person的说话继承下来
dad.say() // Error dad say is not a function
要想继承prototype,最佳的方式是调用Object.create方法
function __inheritProto ( subClass, superClass ) {
const subProto = Object.create(superClass.prototype)
subProto.constructor = subClass //必须将constructor指向直属的构造器
return subProto
}
完整示例:
function Person () {
this.head = 1;
this.shoulders = 2; //两个肩膀扛一个脑袋
}
//将可以复用的方法放入prototype中
Person.prototype.say = function () {
console.log('hello')
}
function Father () {
Person.call(this)
this.gender = 'male' //性别男
}
Father.prototype = __inheritProto(Father,Person);
function __inheritProto ( subClass, superClass ) {
const subProto = Object.create(superClass.prototype)
subProto.constructor = subClass //必须将constructor指向直属的构造器
return subProto
}
let dad = new Fataher()
father.head // 1
father.shouders // 2
father.gender // male
father.say() // hello
另一种实践
直接把子类的prototype引向父类
function Person () {
this.head = 1;
this.shoulders = 2; //两个肩膀扛一个脑袋
}
//将可以复用的方法放入prototype中
Person.prototype.say = function () {
console.log('hello')
}
// 哪吒,仙人也是人
function Nezha () {
this.head = 3;
this.shoulders = 6; //虽然肩膀不算手臂,但不要在意这些细节;
this.gender = 'male' //性别男
}
Nezha.prototype = new Person()
Nezha.prototype.constructor = Nezha
let nz = new Nezha()
nz.head // 3 根据就近原则,子类有的属性就不用去__proto__上找了,下同
nz.shouders // 6
nz.gender // male
nz.say() // hello