完整高频题库仓库地址:https://github.com/hzfe/awesome-interview

完整高频题库阅读地址:https://febook.hzfe.org/

相关问题

  • 关于 ES5 和 ES6 的继承问题

  • 原型链概念

回答关键点

原型链继承 构造函数继承 ES6 类继承

继承是指子类型具备父类型的属性和行为,使代码得以复用,做到设计上的分离。JavaScript 中的继承主要通过原型链和构造函数来实现。常见的继承方法有:ES6 中 class 的继承、原型链继承、寄生组合式继承等。

知识点深入

1. 原型链

原型链的本质是拓展原型搜索机制。每个实例对象都有一个私有属性 __proto__。该属性指向它的构造函数的原型对象 prototype。该原型对象的 __proto__ 也可以指向其他构造函数的 prototype。依次层层向上,直到一个对象的 __proto__ 指向 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。

当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或直到这个链表结束(Object.prototype.__proto__ === null)。

2. 原型链继承

原型链继承的思想:一个引用类型继承另一个引用类型的属性和方法

function SuperType() {this.b = [1, 2, 3];
}function SubType() {}SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;var sub1 = new SubType();
var sub2 = new SubType();// 这里对引用类型的数据进行操作
sub1.b.push(4);console.log(sub1.b); // [1,2,3,4]
console.log(sub2.b); // [1,2,3,4]
console.log(sub1 instanceof SuperType); // true

优点:

  1. 父类新增原型方法/原型属性,子类都能访问到。

  2. 简单、易于实现。

缺点:

  1. 无法实现多继承。

  2. 由于原型中的引用值被共享,导致实例上的修改会直接影响到原型。

  3. 创建子类实例时,无法向父类构造函数传参。

3. 构造函数继承

构造函数继承的思想:子类型构造函数中调用父类的构造函数,使所有需要继承的属性都定义在实例对象上

function SuperType(name) {this.name = name;this.b = [1, 2, 3];
}SuperType.prototype.say = function () {console.log("HZFE");
};function SubType(name) {SuperType.call(this, name);
}var sub1 = new SubType();
var sub2 = new SubType();// 传递参数
var sub3 = new SubType("Hzfe");sub1.say(); // 使用构造函数继承并没有访问到原型链,say 方法不能调用console.log(sub3.name); // Hzfesub1.b.push(4);// 解决了原型链继承中子类实例共享父类引用属性的问题
console.log(sub1.b); // [1,2,3,4]
console.log(sub2.b); // [1,2,3]
console.log(sub1 instanceof SuperType); // false

优点:

  1. 解决了原型链继承中子类实例共享父类引用属性的问题。

  2. 可以在子类型构造函数中向父类构造函数传递参数。

  3. 可以实现多继承(call 多个父类对象)。

缺点:

  1. 实例并不是父类的实例,只是子类的实例。

  2. 只能继承父类的实例属性和方法,不能继承原型属性和方法。

  3. 无法实现函数复用,每个子类都有父类实例函数的副本,影响性能。

4. 组合继承(伪经典继承)

组合继承的思想:使用原型链实现对原型属性和方法的继承,借用构造函数实现对实例属性的继承

function SuperType(name) {this.name = name;this.a = "HZFE";this.b = [1, 2, 3, 4];
}SuperType.prototype.say = function () {console.log("HZFE");
};function SubType(name) {SuperType.call(this, name); // 第二次调用 SuperType
}SubType.prototype = new SuperType(); // 第一次调用 SuperType
SubType.prototype.constructor = SubType;

优点:

  1. 可以继承实例属性/方法,也可以继承原型属性/方法。

  2. 不存在引用属性共享问题。

  3. 可传参

  4. 函数可复用

缺点:

  1. 调用了两次父类构造函数(耗内存),生成了两份实例。

5. 寄生组合式继承

寄生组合式继承的思想:借用构造函数来继承属性,使用混合式原型链继承方法

// 在函数内部,第一步创建父类原型的一个副本,第二部是为创建的副本添加 constructor 属性,
// 从而弥补因重写而失去的默认的 constructor 属性。最后一步,将新创建的对象(即副本)赋值给予类型的原型。
function inheritPrototype(subType, superType) {var prototype = Object.create(superType.prototype); // 创建对象prototype.constructor = subType; // 增强对象subType.prototype = prototype; // 指定对象
}function SuperType(name) {this.name = name;
}SuperType.prototype.sayName = function () {console.log(this.name);
};function SubType(name, num) {SuperType.call(this, name);this.num = num;
}inheritPrototype(SubType, SuperType);SubType.prototype.sayNum = function () {console.log(this.num);
};

优点:

  1. 只调用了一次 SuperType 构造函数,避免了在 SubType.prototype 上创建不必要的属性。

  2. 能够正常使用 instanceof 和 isPrototypeOf()。

缺点:

  1. 实现较为复杂

6. ES6 中 class 的继承

ES6 中引入了 class 关键字, class 可以通过 extends 关键字实现继承,还可以通过 static 关键字定义类的静态方法,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。需要注意的是:class 关键字只是原型的语法糖, JavaScript 继承仍然是基于原型实现的。

class Pet {constructor(name, age) {this.name = name;this.age = age;}showName() {console.log("调用父类的方法");console.log(this.name, this.age);}
}// 定义一个子类
class Dog extends Pet {constructor(name, age, color) {super(name, age); // 通过 super 调用父类的构造方法this.color = color;}showName() {console.log("调用子类的方法");console.log(this.name, this.age, this.color);}
}

优点:

  1. 清晰方便

缺点:

  1. 不是所有的浏览器都支持 class。

参考资料

  1. JS 实现继承的几种方式
  2. 阮一峰 ES6 入门之 class 的继承
  3. 《JavaScript 高级程序设计》
  4. 《你不知道的 JavaScript》

ES5、ES6 如何实现继承相关推荐

  1. ES5和ES6中对于继承的实现方法

    在ES5继承的实现非常有趣的,由于没有传统面向对象类的概念,Javascript利用原型链的特性来实现继承,这其中有很多的属性指向和需要注意的地方. 原型链的特点和实现已经在之前的一篇整理说过了,就是 ...

  2. typescript学习之路(四) —— ts类的继承(包含es5以及es6的类继承)

    上一文已经写了es5,es6等类的定义,所以本章主要写es5和es6的继承,由于es6的继承和ts的继承如出一辙,只是加了类型定义而已,所以ts的继承稍微写下,不会太详细. 文章目录 es5继承 原型 ...

  3. es5/es6 继承总结

    ES5中的继承 一 原型链继承 原型链继承的原理:直接让子类的原型对象指向父类实例,当子类实例找不到对应的属性和方法时,就会往它的原型对象,也就是父类实例上找,从而实现对父类的属性和方法的继承. // ...

  4. 从babel实现es6类的继承来深入理解js的原型及继承

    先聊个5毛钱的背景吧 自从有了babel这一个利器之后,es6现在已经被广泛的使用.JavaScript 类实质上是 JavaScript 现有的基于原型的继承的语法糖.类语法不会为JavaScrip ...

  5. Js Array数组ES5/ES6常用方法

    Js Array数组ES5/ES6常用方法 1.栈方法(先进后出) push():在数组的最后一项后追加值(参数:可以为多个值或数组) 返回:数组的长度,改变了原数组. var a=[1,2,3] a ...

  6. ES5常用的组合继承及原型链理解

    ES5常用的组合继承及原型链理解 <!DOCTYPE html> <html lang="en"><head><meta charset= ...

  7. JavaScript get set方法 ES5 ES6写法

    title: JavaScript get set方法 ES5/ES6写法 date: 2018-05-07 10:38:50 tags: 前端 categories: 前端 网上鲜有get和set的 ...

  8. es6 Class 的继承简介

    简介 ES6 Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多. class Point { } class ColorPoint exten ...

  9. ES6——Class 的继承 笔记

    Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多. class ColorPoint extends Point {constructor(x ...

最新文章

  1. html随机数游戏,js实现随机数小游戏
  2. 手机编程micropython_MicroPython可视化拼插编辑器:让硬件编程更智能!
  3. reactJS -- 9 组件的Refs(操作DOM的两种方法)
  4. 乐鑫代理启明云端分享:用ESP32单片机控制LED教程示例
  5. 浅析概率中的频率学派观点和贝叶斯学派观点
  6. 四步相移法怎么获得相位信息_不一样的费曼学习法!|高中篇|”
  7. 80.共享内存实现进程通信
  8. Java格式化SQL语句
  9. 四川大学本科教务系统 - 一键评教
  10. autoshape很多 excel_怎样清除excle中Autoshape_ExceL批注属性批量修改宏代码�9�3
  11. 可编程串行通信接口芯片8251A
  12. python算方差_Python求均值,方差,标准差的实例
  13. google 浏览器下载历史版本的方法
  14. 数学——Lipschitz连续
  15. 天猫爬虫--爬取天猫评论中的图片
  16. 离散数学-集合论-关系的概念、表示和运算(7)
  17. mysql统计没有参加考试的学生名单_sQL SERVER,帮我编写一个存储过程,查询没有参加考试的学生名单,要求显示姓名、学号,具体请补充:...
  18. Linux查看实时网速的Shell
  19. 对面向接口编程的理解
  20. [CIKM 2019]Balance in Signed Bipartite Networks

热门文章

  1. 楼上噪音让我再也不能愉快的撸代码了!
  2. 树莓派 --- 使用snowboy实现语音唤醒功能
  3. Web3到底是什么?和区块链有啥关系?
  4. 关于S5PV210 LVDS/VGA等方案的考虑——关于SDA7123和ch7034的性价比分析
  5. 字节跳动再战互联网+教育 , 大数据赋能精准教学有何趋势?
  6. yuv色彩空间和色彩范围
  7. 家政服务APP小程序开发功能详解
  8. windows命令提示符_如何在Windows命令提示符中使用命令历史记录
  9. request对象的相关方法和获取request对象的方式
  10. 软件测试可以发现系统所有Bug吗?