1、原型链继承
function Parent() {
this.name = "niuzai";
this.hobby = ['篮球', '游戏']
}
Parent.prototype.getName = function () {
console.log(this.name);
};
function Child() {}
Child.prototype = new Parent();
缺点:
- 引用类型的属性被所有实例共享
- 在创建 Child 的实例时,不能向Parent传参
2、借用构造函数(经典继承)
function Parent() {
this.names = ["kevin", "daisy"];
}
function Child() {
Parent.call(this);
}
优点:
- 解决了原型链继承的 2 个问题:引用类型共享问题以及传参问题 缺点:
- 方法必须定义在构造函数中,所以会导致每次创建子类实例都会创建一遍方法。
3、组合继承
function Parent(name) {
this.name = name;
this.colors = ["red", "blue", "green"];
}
Parent.prototype.getName = function () {
console.log(this.name);
};
function Child(name, age) {
Parent.call(this, name);
this.age = age;
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;
优点:
- 融合原型链继承和构造函数的优点 缺点:
- 调用了 2 次父类构造函数,第一次是在 new Parent(),第二次是在 Parent.call()
4、寄生组合式继承
function Parent(name) {
this.name = name;
this.colors = ["red", "blue", "green"];
}
Parent.prototype.getName = function () {
console.log(this.name);
};
function Child(name, age) {
Parent.call(this, name);
this.age = age;
}
// 关键的三步
var F = function () {};
F.prototype = Parent.prototype;
Child.prototype = new F();
封装
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
function prototype(child, parent) {
var prototype = object(parent.prototype);
prototype.constructor = child;
child.prototype = prototype;
}
// 当我们使用的时候:
prototype(Child, Parent);
优点: 解决了调用了 2 次父类构造函数
5、ES6 class继承
class Parent {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
class Child extends Animal {
constructor(name, age) {
super(name);
this.age = age;
}
}