对于JavaScript继承你到底了解多少

 更新时间:2021年09月07日 09:25:28   作者:柒天后  
js的继承机制不同于传统的面向对象语言,采用原型链实现继承,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法,下面这篇文章主要给大家介绍了关于JS继承的相关资料,需要的朋友可以参考下

前言

关于继承,你到底了解多少,什么样的继承是最最优的,让我们一起来学习一些关于继承的那些知识点,带你了解他们的实现过程,以及他们的优缺点

构造函数,原型对象,实例对象三者之间的关系

先来了解他们的关系有助于对继承更好的理解

原型链继承

核⼼:将⽗类实例作为⼦类原型

代码实现过程:

function Parent(name){
    this.name = name || 'xt',
    this.arr = [1]
}
function Son(age){
    this.age = age
}
Parent.prototype.say = function() { //将需要复⽤、共享的⽅法定义在⽗类原型上
    console.log('hello');
}
Son.prototype = new Parent()
let s1 = new Son(18)
let s2 = new Son(19)
console.log(s1.say() === s2.say()); //true
console.log(s1.name,s1.age); //xt 18
console.log(s2.name,s2.age); //xt 19
s1.arr.push(2)
console.log(s1.arr,s2.arr); // [ 1, 2 ] [ 1, 2 ]

优点:

实例可继承的属性有:实例的构造函数的属性,父类构造函数属性,父类原型的属性。(新实例不会继承父类实例的属性!)

缺点:

  • ⼦类实例共享了⽗类构造函数的引⽤属性,⽐如arr属性(原型上的属性是共享的,一个实例修改了原型属性,另一个实例的原型属性也会被修改!)
  • 不能向⽗类构造函数传参

借⽤构造函数继承

核心:借⽤⽗类的构造函数来增强⼦类实例,等于是复制⽗类的实例属性给⼦类

代码实现:

function Parent(name) {
    this.name = name;
    this.arr = [1],
    this.say = function() { console.log('hello') }
}
function Son(name, age) {
    Parent.call(this, name) // 拷⻉了⽗类的实例属性和⽅法
    this.age = age
}
let s1 = new Son('小谭', 18)
let s2 = new Son('小明', 19)
console.log(s1.say === s2.say) //false ⽅法不能复⽤ ⽅法是独⽴,不是共享的
console.log(s1.name, s1.age); //小谭 18
console.log(s2.name, s2.age); //小明 19
s1.arr.push(2)
console.log(s1.arr, s2.arr); // [ 1, 2 ] [ 1 ]

优点:

  • 只继承了父类构造函数的属性,没有继承父类原型的属性。
  • 可以继承多个构造函数属性(call多个)
  • 在子实例中可向父实例传参。

缺点:

  • 只能继承父类构造函数的属性。
  • 无法实现构造函数的复用。(每次用每次都要重新调用)
  • 每个新实例都有父类构造函数的副本,臃肿。

原型式继承

核心:用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了个可以随意增添属性的实例或对象

function Parent(name) {
    this.name = 'xt';
    this.arr = [1]
}
function object(obj){
    function F(){}
    F.prototype = obj;
    return new F();
  }
let s1 = new Parent(object)
s1.name = '小明'
s1.arr.push(2)
let s2 = new Parent(object)
console.log(s1.name,s2.name); // 小明 xt
console.log(s1.arr, s2.arr); //[ 1, 2 ] [ 1 ]

缺点:

  • 所有实例都会继承原型上的属性,无法传递参数
  • 无法实现复用。(新实例属性都是后面添加的)

寄生式继承

核心:在原型式继承的基础上,增强对象,返回构造函数

function Parent(name) {
    this.name = 'xt';
    this.arr = [1]
}
function object(obj){
    function F(){}
    F.prototype = obj;
    return new F();
  }
let Son = new Parent()
function addobject(obj){
    var add = object(obj)
    add.name = '小白'
    return add
}
var s1 = addobject(Son)
console.log(s1.name); //小白

缺点:

  • 没用到原型,无法复用。
  • 原型链继承多个实例的引用类型属性指向相同,存在篡改的可能。

组合继承(组合原型链继承和借用构造函数继承)

核心:通过调⽤⽗类构造函数,继承⽗类的属性并保留传参的优点;然后通过将⽗类实例作为⼦类原型,实现函数复⽤。

代码实现:

function Parent(name) {
    this.name = name;
    this.arr = [1]
}
Parent.prototype.say = function () { console.log('hello') }
function Son(name, age) {
    Parent.call(this, name) // 二次
    this.age = age
}
Parent.prototype = new Son() // 一次
let s1 = new Son('小谭', 18)
let s2 = new Son('小明', 19)
console.log(s1.say === s2.say) // true
console.log(s1.name, s1.age); //小谭 18
console.log(s2.name, s2.age); //小明 19
s1.arr.push(2)
console.log(s1.arr, s2.arr); // [ 1, 2 ] [ 1 ] 不共享⽗类的引⽤属性,

优点:

  • 保留构造函数的优点:创建⼦类实例,可以向⽗类构造函数传参数。
  • 保留原型链的优点:⽗类的⽅法定义在⽗类的原型对象上,可以实现⽅法复⽤。
  • 不共享⽗类的引⽤属性。⽐如arr属性

缺点:

  • 由于调⽤了2次⽗类的构造⽅法,会存在⼀份多余的⽗类实例属性

寄生组合式继承

核心:结合借用构造函数传递参数和寄生模式实现继承

function Parent(name){
    this.name = name || 'xt',
    this.arr = [1]
}
function Son(name,age){
    Parent.call(this,name) // 核⼼
    this.age = age
}
Parent.prototype.say = function() {  
    console.log('hello');
}
Son.prototype = Object.create(Parent.prototype) // 核心 通过创建中间对象,⼦类原型和⽗类原型,就会隔离开。
Son.prototype.constructor = Son
let p1 = new Parent()

let s1 = new Son("小红",18)
let s2 = new Son("小黑",19)
console.log(p1.constructor); //[Function: Parent]
console.log(s1.constructor); // [Function: Son]
console.log(s1.say() === s2.say()); //true
console.log(s1.name,s1.age); // 小红 18
console.log(s2.name,s2.age); //小黑 19
s1.arr.push(2)
console.log(s1.arr,s2.arr); // [ 1, 2 ] [ 1, 2 ]

寄生式组合继承可以算是引用类型继承的最佳继承

总结

到此这篇关于JS继承的文章就介绍到这了,更多相关JS继承的理解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • javaScript实现滚动条事件详解

    javaScript实现滚动条事件详解

    这篇文章主要为大家详细介绍了javaScript实现滚动条事件的相关资料,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-09-09
  • js简单的弹出框有关闭按钮

    js简单的弹出框有关闭按钮

    这篇文章主要介绍了使用js做的一个简单的弹出框且有关闭按钮,需要的朋友可以参考下
    2014-05-05
  • JavaScript实现数组在指定位置插入若干元素的方法

    JavaScript实现数组在指定位置插入若干元素的方法

    这篇文章主要介绍了JavaScript实现数组在指定位置插入若干元素的方法,涉及javascript中splice方法的使用技巧,非常具有实用价值,需要的朋友可以参考下
    2015-04-04
  • JavaScript使用prototype原型实现的封装继承多态示例

    JavaScript使用prototype原型实现的封装继承多态示例

    这篇文章主要介绍了JavaScript使用prototype原型实现的封装继承多态,涉及javascript prototype与面向对象程序设计相关操作技巧,需要的朋友可以参考下
    2018-08-08
  • JS中自定义事件的使用与触发操作实例分析

    JS中自定义事件的使用与触发操作实例分析

    这篇文章主要介绍了JS中自定义事件的使用与触发操作,结合实例形式分析了JavaScript自定义事件的创建、监听、触发相关原理与使用技巧,需要的朋友可以参考下
    2019-11-11
  • js实现无缝滚动图

    js实现无缝滚动图

    本文主要分享了js实现无缝滚动图的示例代码,具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • three.js中多线程的使用及性能测试详解

    three.js中多线程的使用及性能测试详解

    这篇文章主要给大家介绍了关于three.js中多线程的使用及性能测试的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • 简单聊聊JavaScript中的事件循环

    简单聊聊JavaScript中的事件循环

    js的事件循环(event-loop)是我们前端学习中非常重要的一部分,也是面试中经常被问到的点,这篇文章我们就来给大家着重讲解一下吧
    2023-02-02
  • echarts饼图各个板块之间的空隙如何实现

    echarts饼图各个板块之间的空隙如何实现

    这篇文章主要给大家介绍了关于echarts饼图各个板块之间的空隙如何实现的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12

最新评论