继承是指子类拥有父类的所有属性与方法,而无需重新定义。
class实现继承
es6新引入的class关键字具有正式定义类的能力,class之间通过使用extends关键字实现继承,这比通过修改原型链实现继承,要方便清晰很多
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class Parent { constructor(name) { this.name = name; } sayHello() { console.log('hello'); } sayName() { console.log('my name is ' + this.name); } } class Child extends Parent { constructor(name, age) { super(name); this.age = age; } sayAge() { console.log('my age is ' + this.age); return this.age; } } let child = new Child('小明', 23) child.sayHello() child.sayName() child.sayAge()
|
原型链继承
思路:将父类的实例作为子类的原型
缺点:来自原型对象的所有属性被所有实例共享
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| function Parent(name) { this.name = name; this.colors = ["red", "blue", "green"]; this.sayHello = function () { console.log('hello'); } } Parent.prototype.sayHi = function () { console.log('hi'); }; function Child(name, age) { this.age = age; } Child.prototype = new Parent(); let child = new Child('小明', 23); child.colors.push('black') console.log(child.name); console.log(child.age); console.log(child.colors); child.sayHello() child.sayHi()
let child1 = new Child('小明1', 23); console.log(child1.colors);
|
构造继承(经典继承)
思路:在子类构造函数中调用父类构造函数
缺点:只能继承父类的实例属性和方法,不能继承原型属性/方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function Parent(name) { this.name = name; this.sayHello = function () { console.log('hello'); } }
Parent.prototype.sayHi = function () { console.log('hi'); }; function Child(name, age) { Parent.call(this, name); this.age = age; } let child = new Child('小明', 23); console.log(child.name); console.log(child.age); child.sayHello() child.sayHi()
|
组合继承
组合继承弥补了原型链和盗用构造函数的不足,是JavaScript中使用最多的继承模式。而且组合继承也保留了instanceof操作符和isPrototypeOf()方法识别合成对象的能力。
思路:使用原型链继承原型上的属性和方法,而通过盗用构造函数继承实例属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function Parent(name) { this.name = name; this.sayHello = function () { console.log('hello'); } } Parent.prototype.sayHi = function () { console.log('hi'); }; function Child(name, age) { Parent.call(this, name); this.age = age; } Child.prototype = new Parent(); Child.prototype.constructor = Child; let child = new Child('小明', 23); console.log(child.name); console.log(child.age); child.sayHello() child.sayHi()
|
原型式继承
思路:实现思路就是将子类的原型设置为父类的原型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| function Parent(name) { this.name = name; this.sayHello = function () { console.log('hello'); } } Parent.prototype.sayHi = function () { console.log('hi'); }; function Child(name, age) { Parent.call(this, name) this.age = age; }
Child.prototype = Object.create(Parent.prototype, { constructor: { value: Child, enumerable: false, writable: true, configurable: true } }) let child = new Child('小明', 23); console.log(child.name); console.log(child.age); child.sayHello() child.sayHi()
|
寄生式组合继承
思路:借用构造函数继承属性,通过原型链的混成形式来继承方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function Parent(name) { this.name = name; this.sayHello = function () { console.log('hello'); } } Parent.prototype.sayHi = function () { console.log('hi'); }; function Child(name, age) { Parent.call(this, name) this.age = age; } Child.prototype = Object.create(Parent.prototype) Child.prototype.constructor = Child; let child = new Child('小明', 23); console.log(child.name); console.log(child.age); child.sayHello() child.sayHi()
|
参考资料:
JS 继承的 六 种实现方式