你应该掌握的四种继承方式

什么是继承?

继承是类与类之间的关系,其作用是使得子类具有父类别的各种属性和方法。

继承方式

原型链继承

将父类的实例作为子类的原型

function Person() {
  this.name = 'XD';
}
Person.prototype.getName = function () {
  console.log(this.name);
};
function Child() {}
Child.prototype = new Person();
var child = new Child();
child.getName();

缺点:1) 我们无法在继承的时候向 Person 传参
   2) 引用类型的属性被所有实例共享
   3) 由于直接修改 prototype 指向,所以无法多继承

看下面例子

function Person() {
  this.name = 'xiaopao';
  this.colors = ['red', 'blue', 'green']; //引用类型属性
}

Person.prototype.getName = function () {
  console.log(this.name);
};

function Child() {}

Child.prototype = new Person();
var child1 = new Child();
var child2 = new Child();
child1.colors.push('yellow');
console.log(child1.colors); //['red', 'blue', 'green','yellow']
console.log(child2.colors); //['red', 'blue', 'green','yellow']

借用构造函数继承

在子类型构造函数中通用call()调用父类型构造函数

function Person(name) {
  this.name = name;
}
Person.prototype.getName = function () {
  console.log(this.name);
};
function Child(name) {
  Person.call(this, name);
  this.age = 18;
}
var child = new Child('XD');
console.log(child);
console.log(child.getName());//报错

缺点:1) 方法都在构造函数中定义,每次创建实例都会创建一遍方法
   2) 只能继承父类的构造属性和方法,不能继承原型属性和方法

组合继承

第一版

function Animal(name) {
  this.name = name;
  this.skinColors = ['black', 'white'];
}
Animal.prototype.eat = function (food) {
  return `${this.name} eat ${food}`;
};

function Dog() {
  Animal.call(this);
}
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;

var dog1 = new Dog();
dog1.name = 'keji';
dog1.skinColors.push('red');
console.log(dog1.eat('bone'));
console.log(dog1.skinColors); // [ 'black', 'white', 'red' ]
console.log(dog1 instanceof Dog); // true
console.log(dog1 instanceof Animal); // true

var dog2 = new Dog();
console.log(dog2.skinColors); // [ 'black', 'white' ]

缺点: 1) 调用了两次父类的构造函数,有些许损耗性能

升级版

function Animal(name) {
  this.name = name;
  this.skinColors = ['black', 'white'];
}
Animal.prototype.eat = function (food) {
  return `${this.name} eat ${food}`;
};

function Dog() {
  Animal.call(this);
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

var dog1 = new Dog();
dog1.name = 'keji';
dog1.skinColors.push('red');
console.log(dog1.eat('bone'));
console.log(dog1.skinColors); // [ 'black', 'white', 'red' ]
console.log(dog1 instanceof Dog); // true
console.log(dog1 instanceof Animal); // true

var dog2 = new Dog();
console.log(dog2.skinColors); // [ 'black', 'white' ]

修复了缺点一

圣杯继承

//封装继承过程的函数
function inherit(target, origin) {
  var F = function () {};
  F.prototype = origin.prototype;
  target.prototype = new F();
  target.prototype.constructor = target;
  target.prototype.uber = F.prototype; //新增uber属性,记录继承自谁
}
function Animal(name) {
  this.name = name;
  this.skinColors = ['black', 'white'];
}
function Dog() {
  Animal.call(this);
}

inherit(Dog, Animal);

优点: 1) 中间生成了一个对象,起到了隔离的作用。既可以有父辈的属性和方法,改变自己的时候,也不会影响父辈的属性
    2) 不会共享引用类型的构造属性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值