谈谈我对JavaScript继承的理解
发表一下我对于js继承的拙见,理解的深度比较浅,还望各位指点。
这里先写一个公共的父类
function Person (name, age) {
this.name = name;
this.age = age || 23;
this.sayName = function () {
console.log(`hello ${this.name}`)
}
}
Person.prototype = {
getAge: function () {
console.log(`age: ${this.age}`);
}
};
1、构造继承
把所有的属性和方法都放在构造函数内,在子类中调用父类的构造函数,相当于把父类的东西全部移到子类上
/**
* 1、构造函数继承
* @constructor
*/
function Man() {
Person.call(this);
this.sex = 'man';
}
var man = new Man();
console.log(man instanceof Man);// true,是子类的实例
console.log(man instanceof Person);// false,不是父类的实例
man.sayName();// 正常输出
man.getAge();// man.getAge is not a function,没有把原型链上的函数也添加到子类实例上
2、原型链继承
子类把所有属性和方法都放在原型链上,并把父类的实例放在子类的原型链上
原型链继承中,原型链上的方法和属性都是所有实例共享的,以为着你在实例A中修改原型链上的属性,实例B中也被修改了
function Man () {}
Man.prototype = new Person();
Man.prototype.getSex = function () {
console.log(`sex ${this.sex}`);
};
var man = new Man();
console.log(man instanceof Man);// true,是子类的实例
console.log(man instanceof Person);// true,是父类的实例
man.sayName();// 正常输出
man.getAge();// 正常输出
3、组合继承
即同时使用构造函数继承和原型链继承。
构造函数继承父类的构造函数类的属性,原型链继承来继承原型链上的属性(一般是把属性放在构造函数内,保证每个子类实例的属性独立,把方法放到原型链上实现函数的复用)
唯一缺点是调用了两次父类构造函数(构造函数内一次,原型链上一次)
/**
* 3、组合继承
* @constructor
*/
function Man (name) {
Person.call(this, name);
this.sex = 'man';
}
Man.prototype = new Person();
Man.prototype.constructor = Man;
Man.prototype.getSex = function () {
console.log(`sex ${this.sex}`);
};
var man = new Man();
console.log(man instanceof Man);// true
console.log(man instanceof Person);// true
man.sayName();// 正常输出
man.getAge();// 正常输出
4、寄生组合继承
最完美的一种继承,但是实现比较复杂,修复了组合继承的缺点
/**
* 4、寄生组合继承
* @param name
* @constructor
*/
function Man(name) {
Person.call(this);
this.name = name;
}
function inherit(subType,superType){
// 这个函数是最关键的
// 定义一个空的类
function F () {}
// 把父类的原型链取出来
F.prototype = superType.prototype;
// 保存父类原型链
let prototype = new F();
/*---以上三行代码可以用ES5的这一行代码代替:var prototype=Object.create(superType.prototype); ---*/
// 修正原型链的构造函数
prototype.constructor = subType;
// 把父类的原型链赋值给子类的原型链
subType.prototype = prototype;
}
inherit(Man, Person);
var man = new Man();
console.log(man);
console.log(man instanceof Man);// true
console.log(man instanceof Person);// true
man.sayName();// 正常输出
man.getAge();// 正常输出
关于继承红宝书也说得很详细,这里再推荐一篇博文,写的也非常浅显→JS实现继承的几种方式
如果有什么问题还希望大家不吝赐教