1.原型链继承
将父类的实例作为子类的原型
function Father(name, age) {
this.name = name;
this.age = age
};
function Son() {};
Son.prototype = new Father();
Son.prototype.constructor = Son;
优点:
1.简单易于实现
2.可以继承父类中的方法
3.实例既是父类实例也是子类实例
缺点:
1.每个实例对引用类型属性的修改都会被其他的实例共享
2.创建子类实例时,无法向父类构造函数传参
3.无法实现多继承
2.构造继承
在子类的构造函数中调用父类的构造函数
function Father(name, age) {
this.name = name;
this.age = age
};
function Son() {
Father.call(this)
};
优点:
1.每个实例对引用类型属性的修改不会被其他的实例共享
2.创建子类实例时,可以向父类构造函数传参
3.可以实现多继承
缺点:
1.只能继承父类的实例属性和方法,不能继承原型属性/方法
2.实例只是子类的实例
3.父类方法无法复用
3.组合继承
将原型链继承和构造继承进行组合
在子类中调用父类的构造函数,将父类实例对象作为子类的原型
function Father(name, age) {
this.name = name;
this.age = age
};
function Son() {
Father.call(this)
};
Son.prototype = new Father();
Son.prototype.constructor = Son;
特点:
1.每个实例对引用类型属性的修改不会被其他的实例共享
2.创建子类实例时,可以向父类构造函数传参
3.可以实现多继承
4.可以继承父类的实例属性和方法,也可以继承原型属性/方法
5.既是子类的实例,也是父类的实例
6.可以实现父类方法的复用
缺点:
调用了两次父类,产生了两个实例对象
4.拷贝继承
在子类构造函数中创建父类实例对象,利用for in遍历出父类实例对象的键名,并添加到子类的原型上
function Father(name, age) {
this.name = name;
this.age = age
};
function Son() {
let father = new Father();
for (let i in father) {
Son.prototype[i] = father[i]
}
};
优点:
1.支持多继承
缺点:
1.效率极低,内存占用高(因为要拷贝父类的属性)
2.无法获取父类不可枚举的方法(for in不能访问到的)
5.原型式继承(实例继承)
创建父类的实例对象,以父类实例对象为原型对象创建子类构造函数,利用该构造函数产生子类对象
function Father(name, age) {
this.name = name;
this.age = age
};
function beget(obj) {
let F = function() {};
F.prototype = obj;
return new F()
};
let father = new Father();
let son = beget(father)
特点:
从父类对象直接产生新的对象
缺点:
1.每个实例对引用类型属性的修改都会被其他的实例共享
2.实例只是子类的实例
3.父类方法无法复用
2.不支持多继承
6.寄生式继承
创建父类的实例对象,以父类实例对象为原型对象创建子类构造函数,利用该构造函数产生子类对象,并且以某种方法增强这个对象
function Father(name, age) {
this.name = name;
this.age = age
};
function beget(obj) {
let F = function() {};
F.prototype = obj;
return new F()
};
function create(obj) {
let temp = beget(obj);
temp.hello = function() {
console.log("hello");
};
return temp
}
let father = new Father();
let son = create(father)
特点:
从父类对象直接产生新的对象
缺点:
1.每个实例对引用类型属性的修改都会被其他的实例共享
2.实例只是子类的实例
3.父类方法无法复用
2.不支持多继承
7.寄生组合继承
通过寄生方式,砍掉父类的实例属性,这样,在调用俩次父类的构造的时候,就不会初始化俩次实例方法/属性,避免了组合继承的缺点。
function Father(name, age) {
this.name = name;
this.age = age
};
function beget(obj) {
let F = function() {};
F.prototype = obj;
return new F()
};
function Son() {
Father.call(this)
}
let proto = beget(Father.prototype);
proto.constructor = Son;
Son.prototype = proto;
let son = new Son()
特点:
基本上是完美的
缺点:
实现起来较为复杂
7.class
本质上还是原型链继承
class Point {
constructor(x, y) {
this.x = x
this.y = y
}
toString() {
return this.x + '' + this.y
}
}
class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y) //调用父类的constructor(x, y)
this.color = color
}
toString() {
return this.color + ' ' + super.toString() // 调用父类的toString()
}
}
var colorPoint = new ColorPoint('1', '2', 'red')
console.log(colorPoint.toString()) // red 12
本文详细介绍了JavaScript中包括原型链继承、构造继承、组合继承、拷贝继承、原型式继承、寄生式继承和寄生组合继承以及ES6的class实现。分析了各种继承方式的优缺点,如原型链继承的共享引用类型问题,构造继承无法继承原型属性,组合继承的重复调用,拷贝继承的低效率等。最后指出,寄生组合继承被认为是较为完美的继承方式,但实现相对复杂。
288

被折叠的 条评论
为什么被折叠?



