JS实现继承
方式一:借助call
function Parent1() {
this.name = 'parent1';
}
function Children1() {
Parent1.call(this);
this.type = 'children1';
}
console.log(new Children1());
// 子类虽然能够拿到父类的属性值,但父类原型对象中的方法,子类无法继承。
方式二:借助原型链
function Parent2() {
this.name = 'parent2';
this.arr = [1,2,3];
}
function Children2() {
this.type = 'children2';
}
Children2.prototype = new Parent2();
console.log(new Children2());
// 多个实例都是使用同一个原型对象,也就是改变其中一个实例,另外的实例也会变化。
let s1 = new Children2();
let s2 = new Children2();
s1.name = 's1_parent2';
console.log(s1.name, s2.name); // 都输出 s1_parent2
方式三:call + 原型链
function Parent3() {
this.name = 'parent3';
this.arr = [1,2,3];
}
function Children3() {
Parent3.call(this);
this.type = 'children3';
}
Children3.prototype = new Parent3();
// 虽然解决了上面所说的问题,但又徒增了一个新问题。
// Parent3的构造函数会多执行了一次Children3.prototype = new Parent3();
方式四:组合继承
function Parent4() {
this.name = 'parent4';
this.arr = [1,2,3];
}
function Children4() {
Parent4.call(this);
this.type = 'children4';
}
Children4.prototype = Parent4.prototype;
// 这里将父类原型对象直接给到子类,父类构造函数只执行一次,而且父类属性和方法均能访问到。
// 但有另外一个问题,就是子类实例化的对象的构造函数将是Parent4。
方式五:寄生组合继承
function Parent5() {
this.name = 'parent5';
this.arr = [1,2,3];
}
function Children5() {
Parent5.call(this);
this.type = 'children5';
}
Children5.prototype = Object.create(Parent5.prototype);
Children5.prototype.constructor = Children5;
// 这是最好的一种方式,接近完美的继承。
// 最关键的是把子类的原型对象的constructor重新连接到子类身上。