第一种: 借助call
function Parent1() {
(this.name = "parent1"),
function () {
console.log("方法");
};
}
function Child1() {
Parent1.call(this);
this.type = "child1";
}
let a = new Child1();
console.log(a); //name: "parent1" type: "child1"
//虽然能够拿到父类的属性值,
//但是问题是父类原型对象中一旦存在方法那么子类无法继承
第二种: 借助原型链
function Parent2() {
this.name = "parent2";
this.play = [1, 2, 3];
}
function Child2() {
this.type = "child2";
}
Child2.prototype = new Parent2();
console.log(new Child2());
var s1 = new Child2();
var s2 = new Child2();
s1.play.push(4);
console.log(s1.play, s2.play); //(4) [1, 2, 3, 4] (4) [1, 2, 3, 4]
// 明明我只改变了s1的play属性,为什么s2也跟着变了呢?
// 很简单,因为两个实例使用的是同一个原型对象
注意的点:实际上这个方法主要实现了可以继承父的方法
第三种:将前两种组合
function Parent3() {
this.name = "parent3";
this.play = [1, 2, 3];
}
function Child3() {
Parent3.call(this);
this.type = "child3";
}
Child3.prototype = new Parent3();
var s3 = new Child3();
var s4 = new Child3();
console.log(s3);
s3.play.push(4);
console.log(s3.play, s4.play); //(4) [1, 2, 3, 4] (3) [1, 2, 3]
//但是这里又徒增了一个新问题,
//那就是Parent3的构造函数会多执行了一次(Child3.prototype = new Parent3();)
注意的点:
-
上一个方法相当于通过原型链访问父类上的属性,同一个父类,所以属性是同一个
-
而这个方法中,call相当于child3上也有name和play了,执行后每个实例上都有这些属性了,所以互不影响
第四种: 组合继承的优化1
function Parent4() {
this.name = "parent4";
this.play = [1, 2, 3];
}
function Child4() {
Parent4.call(this);
this.type = "child4";
}
Child4.prototype = Parent4.prototype;
var s3 = new Child4();
var s4 = new Child4();
console.log(s3);
// 子类实例的构造函数是Parent4,显然这是不对的,应该是Child4
第五种: 寄生组合继承
function Parent5() {
this.name = "parent5";
this.play = [1, 2, 3];
}
function Child5() {
Parent5.call(this);
this.type = "child5";
}
Child5.prototype = Object.create(Parent5.prototype);
Child5.prototype.constructor = Child5;
var s3 = new Child5();
var s4 = new Child5();
console.log(s3);