JavaScript继承
1. 原型链继承
思路:将父类的实例作为子类的原型
优点:父类方法可以复用
缺点:父类的所有引用属性会被所有的子类共享,更改一个子类的引用属性,其他子类也会受影响;子类型实例不能给父类型构造函数传参。
javascript
function Parent() {
this.isShow = true;
this.info = {
name: 'wp',
age: 18
}
}
function Child() {}
Child.prototype = new Parent()
// Test
let child1 = new Child()
let child2 = new Child()
console.log(child1.info.name) // 可以访问到父类的引用属性,'wp'
child1.info.name = 'wp2'
console.log(child2.info.name) // 修改一个引用属性后,其他子类也会受影响
2. 构造函数继承
思路:在子类构造函数中调用父类构造函数,可以在子类构造函数中使用call
和apply
方法
优点:可以在子类构造函数中向父类传参数;父类的引用属性不会被共享
缺点:子类不能访问父类原型上(Parent.prototype)的方法,因此所有方法属性都写在构造函数中,每次创建实例都会初始化。
javascript
function Parent() {
this.info = {
name: 'wp',
age: 18
}
}
function Child() {
Parent.call(this)
}
// Test
let child1 = new Child()
let child2 = new Child()
child1.info.gender = '男'
console.log(child1.info) // {name: 'wp', age: 18, gender: '男'}
console.log(child2.info) // {name: 'wp', age: 18}
// 传递参数
function Parent(name) {
this.info = { name: name };
}
function Child(name) {
//继承自Parent,并传参
Parent.call(this, name);
//实例属性
this.age = 18
}
let child1 = new Child("yhd");
console.log(child1.info.name); // "yhd"
console.log(child1.age); // 18
let child2 = new Child("wxb");
console.log(child2.info.name); // "wxb"
console.log(child2.age); // 18
3. 组合继承
思路:综合原型链继承和构造函数继承的优点。使用原型链继承原型上的属性和方法,通过构造函数继承实例属性,这样既可以把方法定义在原型上以实现重用,又可以每个实例都有自己的属性。
优点:父类的方法可以复用;可以在Child构造函数中向Parent构造函数中传参;父类构造函数中的引用属性不会被共享。
javascript
function Parent(name) {
this.name = name;
this.colors = ['red', 'blue', 'yellow'];
}
Parent.prototype.sayName = function () {
console.log(this.name);
}
function Child(name, age) {
Parent.call(this, name);
this.age = age;
}
4. 原型式继承
思路:对参数对象浅复制
优点:父类方法可复用
缺点:父类的引用会被所有子类所共享;子类实例不能向父类传参
javascript
function objectCopy(obj) {
function Fn() {};
Fn.prototype = obj;
return new Fn()
}
// 效果类似Object.create()
5. 寄生式继承
思路:构造函数+工厂模式。使用原型式继承对一个目标对象进行浅复制,增强浅复制的能力。
javascript
function objectCopy(obj) {
function Fun() { };
Fun.prototype = obj;
return new Fun();
}
function createAnother(original) {
let clone = objectCopy(original);
clone.getName = function () {
console.log(this.name);
};
return clone;
}
6. 寄生组合继承
优点:只调用一次父类构造函数;Child可以向Parent传参;父类方法可以复用;父类的引用属性不会被共享。寄生式组合继承。
javascript
function objectCopy(obj) {
function Fun() { };
Fun.prototype = obj;
return new Fun();
}
function inheritPrototype(child, parent) {
let prototype = objectCopy(parent.prototype); // 创建对象
prototype.constructor = child; // 增强对象
Child.prototype = prototype; // 赋值对象
}
function Parent(name) {
this.name = name;
this.friends = ["rose", "lily", "tom"]
}
Parent.prototype.sayName = function () {
console.log(this.name);
}
function Child(name, age) {
Parent.call(this, name);
this.age = age;
}
inheritPrototype(Child, Parent);
Child.prototype.sayAge = function () {
console.log(this.age);
}
7. 补充:ES6的extend语法
参考链接:掘金-JS继承