js之继承实现方法

js的继承方式有很多,本文主要介绍以下几种:构造函数继承、原型链继承、组合继承、es6中的class继承这四种。

一、构造函数继承

构造函数一般命名时首字母大写,用来区分于普通函数,内部使用的this对象来指向即将要生成的实例对象,使用New来生成实例对象。

// 这是一个构造函数
function Animal(name) {
  this.name = name;
  this.showName = function() {
    console.log(this.name);
  };
}

function Cat(name) {
  Animal.call(this, name);
  //Animal.bind(this)(name)
  //Animal.apply(this, [name])
}

let cat = new Cat("我是一只猫");
cat.showName();

补充知识:
 call、apply、bind方法的作用都是改变函数的执行环境,第一个参数传入上下文执行环境(this),然后传入函数执行所需的参数。

优点:

  1. 可以在子类型构造函数中向Parent传递参数
  2. 避免了引用类型的属性被所有实例共享

缺点: 

  1. 只能继承构造函数中的属性和方法,而无法继承原型链上的属性和方法

二、原型链继承

利用原型链来实现继承就是让父类的一个实例作为子类的原型 

// 这是一个构造函数
function Animal(name) {
  this.name = name;
  this.showName = function() {
    console.log(this.name);
  };
}

function Cat() {}

//父类的一个实例作为子类的原型
Cat.prototype = new Animal("我是一只猫");
// 注意这里new Animal()生成的父类对象并没有constructor属性,故需添加上
Cat.prototype.constructor = Cat;

let cat = new Cat();
cat.showName();

优点:

  1.  能够继承父类构造函数及其原型链上的全部属性和方法

缺点: 

  1. 引用类型的属性被所有实例共享,一改全改
  2. 在创建 Child 的实例时,不能向Parent传参

三、组合继承

组合构造函数及原型链两种继承方法,从而解决他们存在的缺点

// 这是一个构造函数
function Animal(name) {
  this.name = name;
  this.showName = function() {
    console.log(this.name);
  };
}

function Cat(name) {
  Animal.apply(this, [name]); //第二次调用
}

//父类的一个实例作为子类的原型
Cat.prototype = new Animal();
// 注意这里new Animal()生成的父类对象并没有constructor属性,故需添加上
Cat.prototype.constructor = Cat;

let cat = new Cat("我是一只猫");
cat.showName();

优点:

  1. 解决了原型链继承和构造函数继承存在的问题

缺点: 

  1. 父类的构造函数被调用两次

四、class继承

利用ES6中的extends,写法更加面向对象,原理还是原型链

class Animal {
  constructor(name) {
    this.name = name;
  }
  showName() {
    console.log(this.name);
  }
}

class Cat extends Animal {
  constructor(name) {
    super(name);  //不能少,而且必须写在this前边
    this.type = "宠物";
  }
  showType() {
    console.log(this.type);
  }
}

let cat = new Cat("我是一只猫");
cat.showName();
cat.showType();

优点:

  1. 实现更简单,且不存在不能传参等问题

补充知识super :

super关键字可以当作函数 super() 使用,也可以当作对象 super 使用

1.当做函数使用

在constructor中,表示父类的构造函数,并且子类的构造函数必须执行一次super,即super(name)相当parent.prototype.constructor.call(this,name)

  constructor(name) {
    super(name);
    this.type = "宠物";
  }

super()也可写在子类的构造函数中,写在自定义函数中会报错。 

2.当做对象使用

静态方法中指向父类,在普通方法中指向父类的原型

发布了67 篇原创文章 · 获赞 4 · 访问量 5953

猜你喜欢

转载自blog.csdn.net/DZY_12/article/details/103808471
今日推荐