JavaScript继承

了解JavaScript中的几种继承方法

#

继承在js中占有非常重要的地位,那么在js中有很多中继承的方式,不过每一种继承方式都有优缺点。下面就列举几种继承的方式。 实现继承首先需要一个父类,在js中实际上是没有类的概念,在es6中class虽然很像类,但实际上只是es5上语法糖而已。

# 原型链继承

function Parent () {
  this.name = 'parent';
  this.say = function() {
    console.log('hi',this.name)
  }
}
function Child() {
  this.name = 'child'
}
Child.prototype = new Parent(); // 继承,让子类的原型直接等于父类的一个实例,每个子的实例都会拥有父类的属性
const child1 = new Child();
child1.say();  // hi child 

# 优缺点

  • 优点:简单易于实现,父类的新增的实例与属性子类都能访问
  • 缺点:无法实现多继承 创建子类实例时,不能向父类构造函数中传参数 修改原型上的属性会影响所有实例,引用类型的属性被所有实例共享

# 借用构造函数继承

借用call方法

function Parent () {
  this.name = 'parent';
  this.say = function() {
    console.log('hi',this.name)
  }
}

function Child() {
  Parent.call(this,'parent'); // 继承 
  this.name = 'child'
}

const child2 = new Child();
child2.say();

# 优缺点

  • 优点:解决了子类构造函数向父类构造函数中传递参数 避免了引用类型的属性被所有实例共享 可以实现多继承(call或者apply多个父类)
  • 缺点:只是子类的实例,不是父类的实例 方法都在构造函数中定义,无法复用 不能继承原型属性/方法(Parent.prototype上的内容无法继承),只能继承父类的实例属性和方法

# 组合继承

组合原型链继承和借用构造函数继承 背后的思路是:使用原型链实现对原型方法的继承,而通过借用构造函数来实现对实例属性的继承。

function Parent() {
  this.name = 'parent';
  this.say = function() {
    console.log('hi',this.name)
  }
}

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

function Child(name,age) {
  Parent.call(this,'parent');  // 继承;继承Parent类的方法属性;
  this.name = name;
  this.age =age;
}

Child.prototype = new Parent();  // 继承; 继承父类原型上的方式属性;

const child3 = new Child('cc');
child3.say();
child3.getName();

# 优缺点

  • 优点:融合原型链继承和构造函数的优点,是JavaScript中最常用的继承模式
  • 缺点:调用了两次父类构造函数

# 原型式继承

借助另外一个构造函数。

function Parent() {
  this.name = 'parent';
  this.say = function() {
    console.log('hi',this.name)
  }
}

function Create(f) {
  function F() {};
  F.prototype = f;
  return new F();
}

const parent = new Parent();
const child4 = Create(parent)
child4.say();

# 优缺点

  • 优点:不限制调用方式、简单,易实现
  • 缺点:不能多次继承

# 寄生式继承

可以理解为在原型式继承的基础上增加一些函数或属性

# 寄生组合式继承

所谓寄生组合继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。 其背后的基本思路是:不必为了指定子类型的原型而调用超类型的构造函数,我们所需要的无非就是超类型的原型的一个副本而已。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给予类型的原型。

//父类
function Parent(name,age){
  this.name = name || 'cc'
  this.age = age || 27
  this.say = function(){
    console.log(this.name)
  }
}
//父类方法
Parent.prototype.eat = function(){
  return this.name + this.age + 'eat sleep'
}
//子类
function Child(name,age){
  //继承父类属性
  Parent.call(this,name,age)
}
//继承父类方法
(function(){
  // 创建空类
  let Super = function(){};
  Super.prototype = Parent.prototype;
  //父类的实例作为子类的原型
  Child.prototype = new Super();
})();
//修复构造函数指向问题
Child.prototype.constructor = Child;
const child5 = new Child();
child5.say();
child5.eat();

数组之差

利用lodash的 difference 和 js数组方式找出两个数组的增量与减量

this

# what

什么是this?this是一个指针,指向调用函数的对象。为了搞清this指向问题,我们先要知道this绑定的规则

  • 默认绑定

  • 隐式绑定

  • 显式绑定

  • new绑定