JS继承的几种方式

1. 借助构造函数实现继承
function Parent() {
  this.name = 'parent';
}
function Child() {
  Parent1.call(this);
  this.type = 'child';
}

**缺点:**只能实现部分继承。Child只能继承Parent构造函数里面的属性。不能继承Parent原型链上的。

function Parent1() {
  this.name = 'parent1';
}
Parent1.prototype.say = function() {
};
function Child1() {
  Parent1.call(this);
  this.type = 'child1';
}
console.log(new Child1(), new Child1().say());

JS继承的几种方式_第1张图片

2. 借助原型链实现继承
function Parent() {
  this.name = 'parent';
}
function Child() {
  this.type = 'child';
}
Child.prototype = new Parent();

**缺点:**实例化两个类,修改第一个实例的属性,会牵动第二个实例的属性变化。原因是两个实例的原型对象引用的是同一个对象,都是父类的实例对象。而改变的方法在父类的实例对象上,而且是引用类型。

function Parent2() {
  this.name = 'parent2';
  this.play = [1, 2, 3];
}

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

var s1 = new Child2();
var s2 = new Child2();
s1.play.push(4);
console.log(s1.play, s2.play);

JS继承的几种方式_第2张图片

3. 组合方式
function Parent() {
  this.name = 'parent';
}
function Child() {
  Parent.call(this);
  this.type = 'child';
}
Child.prototype = new Parent();

解决了上面遗留下来的缺点

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();
s3.play.push(4);
console.log(s3.play, s4.play);

JS继承的几种方式_第3张图片

**缺点:**父类构造函数执行了两次。

4. 组合继承的优化1
function Parent() {
  this.name = 'parent';
  this.play = [1, 2, 3];
}
function Child() {
  Parent.call(this);
  this.type = 'child';
}
Child.prototype = Parent.prototype;
var s5 = new Child();
var s6 = new Child();

不仅能把构造体内的函数属性拿到,还可以把原型链上的属性拿到。
**缺点:**用constructor判断实例是哪个构造函数实例化的失效了。上面构造函数的方式也有同样的问题。他们的constructor都指向父类。

function Parent4() {
  this.name = 'parent4';
  this.play = [1, 2, 3];
}

function Child4() {
  Parent4.call(this);
  this.type = 'child4';
}
Child4.prototype = Parent4.prototype;
var s5 = new Child4();
var s6 = new Child4();

console.log(s5 instanceof Child4, s5 instanceof Parent4);
console.log(s5.constructor);

JS继承的几种方式_第4张图片

5. 组合继承的优化2
function Parent() {
  this.name = 'parent5';
  this.play = [1, 2, 3];
}

function Child() {
  Parent.call(this);
  this.type = 'child5';
}
// 产生一个中间对象隔离`Child`的`prototype`属性和`Parent`的`prototype`属性引用的同一个原型。
Child.prototype = Object.create(Parent.prototype); 
// 给Child的原型对象重新写一个自己的constructor。
Child.prototype.constructor = Child;

你可能感兴趣的:(js)