JS继承(不同方式和优缺点)

以下代码可以直接放到控制台看运行结果
1、借助构造函数实现继承,缺点是不能继承Parent1的原型对象

// 借助构造函数实现继承
function Parent1() {
    this.name = 'parent1';
    this.play = [1, 2, 3];
}

function Child1() {
    Parent1.call(this); //apply
    this.type = 'Child1';
}

console.log(new Parent1(), new Child1());
var s1 = new Child1();
var s2 = new Child1();
console.log(s1, s2);//未继承原型对象
console.log(s1.play, s2.play);
s1.play.push(4);
console.log(s1.play, s2.play);

Parent1.prototype.age = 20;
console.log(s1.age, s2.age);

2、借助原型链实现继承,缺点是共享属性和方法

//借助原型链实现继承
function Parent2() {
    this.name = 'parent2';
    this.play = [1, 2, 3];
}

function Child2() {
    this.type = 'Child2';
}
Child2.prototype = new Parent2();

var s3 = new Child2();
var s4 = new Child2();
console.log(s3, s4);
console.log(s3.play, s4.play);
s3.play.push(4);
console.log(s3.play, s4.play);//s3和s4的属性和方法共享

3、组合方式实现继承(原型链继承+绑定this),缺点是Parent3执行两次

// 组合方式
function Parent3() {
    this.name = 'parent3';
    this.play = [1, 2, 3];
}

function Child3() {
    Parent3.call(this);
    this.type = 'Child3';
}
Child3.prototype = new Parent3();

var s5 = new Child3();
var s6 = new Child3();
console.log(s5, s6);//继承了parent3的原型对象
console.log(s5.play, s6.play);
s5.play.push(4);
console.log(s5.play, s6.play);//s5和s6数据对象不同

4、组合方式实现继承优化一,缺点是无法区分实例是由父类创造还是子类创造

//组合方式优化一
function Parent4() {
    this.name = 'parent4';
    this.play = [1, 2, 3];
}

function Child4() {
    Parent4.call(this);
    this.type = 'Child4';
}
Child4.prototype = Parent4.prototype; //不用实例化一个Parent4对象

var s7 = new Child4();
var s8 = new Child4();
console.log(s7.play, s8.play);
s7.play.push(4);
console.log(s7.play, s8.play);
console.log(s7.constructor); //缺点是Child4和Parent4的原型对象相同,构造函数相同
// console.log(Child4.prototype.constructor);
// console.log(s5.__proto__.constructor);
// console.log(s5.__proto__ === Child4.prototype);

5、组合方式实现继承优化二(最优写法)

// 组合继承的优化2(完美写法)
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原型对象是Obejct.create方法的参数
//Object.create方法会丢失原构造函数属性
//它的原型链也是原构造函数(对象)本身,因此还需要指定constructor
Child5.prototype.constructor = Child5;

var s9 = new Child5();
var s10 = new Child5();
s9.play.push(4);
console.log(s9.play, s10.play);
console.log(s9.constructor);
console.log(s9.__proto__ === Child5.prototype);

Parent5.prototype.age = 20;
console.log(s9.age, s10.age);

你可能感兴趣的:(JS继承(不同方式和优缺点))