继承

  • 继承已关闭评论
  • 179 次浏览
  • A+
所属分类:Web前端
摘要

原型链继承构造函数继承借⽤构造函数实现继承解决了原型链继承的 2 个问题:引⽤类型共享问题以及传参问题。但是由于
⽅法必须定义在构造函数中,所以会导致每次创建⼦类实例都会创建⼀遍⽅法。

原型链继承

点击查看代码
function Animal() { this.colors = ['black', 'white'] } Animal.prototype.getColor = function() { return this.colors } function Dog() {} Dog.prototype = new Animal() let dog1 = new Dog() dog1.colors.push('brown') let dog2 = new Dog() console.log(dog2.colors) // ['black', 'white', 'brown'] 

原型链继承存在的问题:

  • 问题1:原型-中包含的引⽤类型属性将被所有实例共享;
  • 问题2:⼦类在实例化的时候不能给⽗类构造函数传参;

构造函数继承

点击查看代码
function Animal(name) { this.name = name this.getName = function() { return this.name } } function Dog(name) { Animal.call(this, name) } Dog.prototype = new Animal() 

借⽤构造函数实现继承解决了原型链继承的 2 个问题:引⽤类型共享问题以及传参问题。但是由于
⽅法必须定义在构造函数中,所以会导致每次创建⼦类实例都会创建⼀遍⽅法。

组合继承
组合继承结合了原型链和盗⽤构造函数,将两者的优点集中了起来。基本的思路是使⽤原型链继承
原型上的属性和⽅法,⽽通过盗⽤构造函数继承实例属性。这样既可以把⽅法定义在原型上以实现
重⽤,⼜可以让每个实例都有⾃⼰的属性。

点击查看代码
function Animal(name) { this.name = name this.colors = ['black', 'white'] } Animal.prototype.getName = function() { return this.name } function Dog(name, age) { Animal.call(this, name) this.age = age } Dog.prototype = new Animal() Dog.prototype.constructor = Dog let dog1 = new Dog('奶昔', 2) dog1.colors.push('brown') let dog2 = new Dog('哈⾚', 1) console.log(dog2) // { name: "哈⾚", colors: ["black", "white"], age: 1 } 

组合寄生式继承(圣杯模式)
组合继承已经相对完善了,但还是存在问题,它的问题就是调⽤了 2 次⽗类构造函数,第⼀次是在
new Animal(),第⼆次是在 Animal.call() 这⾥。
所以解决⽅案就是不直接调⽤⽗类构造函数给⼦类原型赋值,⽽是通过创建空函数 F 获取⽗类原型
的副本。
寄⽣式组合继承写法上和组合继承基本类似,区别是如下这⾥:

点击查看代码
删除: Dog.prototype = new Animal() Dog.prototype.constructor = Dog  增加: function F() {} F.prototype = Animal.prototype let f = new F() f.constructor = Dog Dog.prototype = f  使用ES6中Object.create 增加(不用增加上面那部分了): Dog.prototype = Object.create(Animal.prototype) Dog.prototype.constructor = Dog 

ES6 class extends继承

点击查看代码
class Animal { constructor(name) { this.name = name } getName() { return this.name } } class Dog extends Animal { constructor(name, age) { super(name) this.age = age } }