JavaScript实现继承的6种常用方式总结

 更新时间:2022年07月21日 09:47:33   作者:不愿染是与非  
JavaScript想实现继承的目的:重复利用另外一个对象的属性和方法。本文为大家总结了JavaScript实现继承的6种常用方式,需要的可以参考一下

JavaScript想实现继承的目的:重复利用另外一个对象的属性和方法。

1.原型链继承

让一个构造函数的原型是另一个类型的实例,那么这个构造函数new出来的实例就具有该实例的属性。

当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。

function Parent() {
   this.isShow = true
   this.info = {
       name: "mjy",
       age: 18,
   };
}

Parent.prototype.getInfo = function() {
   console.log(this.info);
   console.log(this.isShow);
}

function Child() {};
Child.prototype = new Parent();

let Child1 = new Child();
Child1.info.gender = "男";
Child1.getInfo(); // {name: 'mjy', age: 18, gender: '男'} ture

let child2 = new Child();
child2.isShow = false
console.log(child2.info.gender) // 男
child2.getInfo(); // {name: 'mjy', age: 18, gender: '男'} false

优点:写法方便简洁,容易理解。

缺点:对象实例共享所有继承的属性和方法。传教子类型实例的时候,不能传递参数,因为这个对象是一次性创建的(没办法定制化)。

2.借用构造函数继承

function Parent(gender) {
  this.info = {
    name: "yhd",
    age: 19,
    gender: gender
  }
}

function Child(gender) {
    Parent.call(this, gender)
}

let child1 = new Child('男');
child1.info.nickname = 'xiaoma'
console.log(child1.info);

let child2 = new Child('女');
console.log(child2.info);

在子类型构造函数的内部调用父类型构造函数;使用 apply() 或 call() 方法将父对象的构造函数绑定在子对象上。

优点:解决了原型链实现继承的不能传参的问题和父类的原型共享的问题。

缺点:借用构造函数的缺点是方法都在构造函数中定义,因此无法实现函数复用。在父类型的原型中定义的方法,对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式。

3.组合继承(经典继承)

将 原型链 和 借用构造函数 的组合到一块。使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数复用,又能够保证每个实例都有自己的属性

function Person(gender) {
  console.log('执行次数');
  this.info = {
    name: "mjy",
    age: 19,
    gender: gender
  }
}

Person.prototype.getInfo = function () {   // 使用原型链继承原型上的属性和方法
  console.log(this.info.name, this.info.age)
}

function Child(gender) {
  Person.call(this, gender) // 使用构造函数法传递参数
}

Child.prototype = new Person()

let child1 = new Child('男');
child1.info.nickname = 'xiaoma'
child1.getInfo()
console.log(child1.info);

let child2 = new Child('女');
console.log(child2.info);

优点就是解决了原型链继承和借用构造函数继承造成的影响。

缺点是无论在什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部

4.原型式继承

方法一:借用构造函数

在一个函数A内部创建一个临时性的构造函数,然后将传入的对象作为这个构造函数的原型,最后返回这个临时类型的一个新实例。本质上,函数A是对传入的对象执行了一次浅复制。

function createObject(obj) {
  function Fun() {}
  Fun.prototype = obj
  return new Fun()
}

let person = {
  name: 'mjy',
  age: 18,
  hoby: ['唱', '跳'],
  showName() {
    console.log('my name is:', this.name)
  }
}

let child1 = createObject(person)
child1.name = 'xxxy'
child1.hoby.push('rap')
let child2 = createObject(person)

console.log(child1)
console.log(child2)
console.log(person.hoby) // ['唱', '跳', 'rap']

方法二:Object.create()

Object.create() 是把现有对象的属性,挂到新建对象的原型上,新建对象为空对象

ECMAScript 5通过增加Object.create()方法将原型式继承的概念规范化了。这个方法接收两个参数:作为新对象原型的对象,以及给新对象定义额外属性的对象(第二个可选)。在只有一个参数时,Object.create()与这里的函数A方法效果相同。

let person = {
  name: 'mjy',
  age: 19,
  hoby: ['唱', '跳'],
  showName() {
    console.log('my name is: ', this.name)
  }
}

let child1 = Object.create(person)
child1.name = 'xxt'
child1.hoby.push('rap')
let child2 = Object.create(person)

console.log(child1)
console.log(child2)
console.log(person.hoby) // ['唱', '跳', 'rap']

优点是:不需要单独创建构造函数。

缺点是:属性中包含的引用值始终会在相关对象间共享,子类实例不能向父类传参

5.寄生式继承

寄生式继承的思路与(寄生) `原型式继承` 和 `工厂模式` 似, 即创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真的是它做了所有工作一样返回对象。

function objectCopy(obj) {
  function Fun() { };
  Fun.prototype = obj;
  return new Fun();
}

function createAnother(obj) {
  let clone = objectCopy(obj);
  clone.showName = function () {
    console.log('my name is:', this.name);
  };
  return clone;
}

let person = {
     name: "mjy",
     age: 18,
     hoby: ['唱', '跳']
}

let child1 = createAnother(person);
child1.hoby.push("rap");
console.log(child1.hoby); // ['唱', '跳', 'rap']
child1.showName(); // my name is: mjy

let child2 = createAnother(person);
console.log(child2.hoby); // ['唱', '跳', 'rap']

优点:写法简单,不需要单独创建构造函数。

缺点:通过寄生式继承给对象添加函数会导致函数难以重用。使用寄生式继承来为对象添加函数, 会由于不能做到函数复用而降低效率;这一点与构造函数模式类似.

6.寄生组合式继承

前面讲过,组合继承是常用的经典继承模式,不过,组合继承最大的问题就是无论什么情况下,都会调用两次父类构造函数;一次是在创建子类型的时候,一次是在子类型的构造函数内部。寄生组合继承就是为了降低父类构造函数的开销而实现的。

通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。

function objectCopy(obj) {
  function Fun() { };
  Fun.prototype = obj;
  return new Fun();
}

function inheritPrototype(child, parent) {
  let prototype = objectCopy(parent.prototype);
  prototype.constructor = child;
  Child.prototype = prototype;
}

function Parent(name) {
  this.name = name;
  this.hoby = ['唱', '跳']
}

Parent.prototype.showName = function () {
  console.log('my name is:', this.name);
}

function Child(name, age) {
  Parent.call(this, name);
  this.age = age;
}

inheritPrototype(Child, Parent);
Child.prototype.showAge = function () {
  console.log('my age is:', this.age);
}

let child1 = new Child("mjy", 18);
child1.showAge(); // 18
child1.showName(); // mjy
child1.hoby.push("rap");
console.log(child1.hoby); // ['唱', '跳', 'rap']

let child2 = new Child("yl", 18);
child2.showAge(); // 18
child2.showName(); // yl
console.log(child2.hoby); // ['唱', '跳']

优点是:高效率只调用一次父构造函数,并且因此避免了在子原型上面创建不必要,多余的属性。与此同时,原型链还能保持不变;

缺点是:代码复杂

7.ES6、Class实现继承

原理ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。 ES6 的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this

优点:语法简单易懂,操作更方便。

缺点:并不是所有的浏览器都支持class关键字 lass Per

以上就是JavaScript实现继承的6种常用方式总结的详细内容,更多关于JavaScript继承的资料请关注脚本之家其它相关文章!

相关文章

  • 详解JavaScript时间处理之几个月前或几个月后的指定日期

    详解JavaScript时间处理之几个月前或几个月后的指定日期

    本篇文章主要介绍了JavaScript时间处理之几个月前或几个月后的指定日期 ,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2016-12-12
  • js事件源window.event.srcElement兼容性写法(详解)

    js事件源window.event.srcElement兼容性写法(详解)

    下面小编就为大家带来一篇js事件源window.event.srcElement兼容性写法(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-11-11
  • H5移动端适配 Flexible方案

    H5移动端适配 Flexible方案

    这篇文章主要为大家详细介绍了H5移动端适配,Flexible方案,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • Javascript 继承机制实例

    Javascript 继承机制实例

    说明继承机制最简单的方法是,利用一个经典的例子——几何形状。
    2009-08-08
  • 巧用数组制作图片切换js代码

    巧用数组制作图片切换js代码

    这篇文章主要为大家详细介绍了巧用数组制作图片切换js实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-11-11
  • JavaScript中的对象和原型(一)

    JavaScript中的对象和原型(一)

    大家都知道在js中没有类的概念,因此它的对象也与基于类的语言中的对象有所不同。所以大家要了解面向对象,首先要了解js中的对象和原型,下面本文给大家介绍JavaScript中的对象和原型(一)知识,一起看下吧
    2016-08-08
  • js实现的复制兼容chrome和IE

    js实现的复制兼容chrome和IE

    这篇文章主要介绍了js在chrome和IE下分别实现复制,需要的朋友可以参考下
    2014-04-04
  • JavaScipt中栈的实现方法

    JavaScipt中栈的实现方法

    这篇文章主要介绍了JavaScript数据结构与算法之栈详解,本文讲解了对栈的操作、对栈的实现实例等内容,需要的朋友可以参考下
    2016-02-02
  • 微信小程序实现点击图片放大预览

    微信小程序实现点击图片放大预览

    这篇文章主要为大家详细介绍了小程序实现点击图片放大预览功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-10-10
  • JS数字抽奖游戏实现方法

    JS数字抽奖游戏实现方法

    这篇文章主要介绍了JS数字抽奖游戏实现方法,可实现按下回车键出现随机数字切换的效果,涉及时间与随机数的相关操作技巧,非常具有实用价值,需要的朋友可以参考下
    2015-05-05

最新评论