这样回答继承可能面试官更满意


Posted in Javascript onDecember 10, 2019

9021年底了,突然想在这个最后一个月准备一下,试试机会,能否更进一步。所以开始准备一些基础知识,也随带总结出来给各位想换工作的同学。希望大家能找到自己想要的工作。祝大家好运!

一、何为继承

一个类获取另一个或者多个类的属性或者方法。继承可以使得子类具有父类的各种方法和属性。以免重复输出很多代码。

二、继承的原理

复制父类的方法和属性来重写子类的原型对象。

三、原型链继承

3.1 实现

function Father() {
  this.text = '1';
}
Father.prototype.someFn = function() {
  console.log(1);
}
Father.prototype.someValue = '2';

function Son(){
  this.text1 = 'text1';
}
// 函数原型指向构造函数的实例
Son.prototype = new Father();

3.2 优点

1、简单易操作。

3.3 缺点

1、父类使用this声明的属性被所有实例共享。原因是实例化是父类一次性赋值到子类实例的原型上,它会将父类通过this声明的属性也赋值到子类原型上。例如在父类中一个数组值,在子类的多个实例中,无论哪一个实例去修改这个数组的值,都会影响到其他子类实例。

2、创建子类实例时,无法向父类构造函数传参,不够灵活。

四、借用构造函数(call)

4.1 实现

function Father(...arr) {
  this.some = '父类属性';
  this.params = arr;
}
Father.prototype.someFn = function() {
  console.log(1);
}
Father.prototype.someValue = '2';
function Son(fatherParams, ...sonParams) {
  // Father的this指向Son的this
  // 使用call调用父类,Father将会立即被执行,并且将父类的Father的this执行Son
  // 的this。实例化子类,this将指向new期间创建的新对象,返回该新对象。
  Father.call(this, ...fatherParams);
  this.text = '子类属性';
  this.sonParams = sonParams;
}
var fatherParams = [];
var sonParams = [];
var sonInstance = new Son(fatherParams, ...sonParams);

4.2 优点

1、可以向父类传递参数。

2、解决父类this声明的属性会被实例共享的问题。

4.3 缺点

1、只能继承父类通过this声明的属性/方法。不能继承父类prototype上的属性/方法。

2、父类方法无法复用。每次实例化子类,都要执行父类函数。重新声明父类所定义的方法,无法复用。

五、组合继承(call+new)

原理:通过原型链继承来将this、prototype上的属性和方法继承制子类的原型对象上。使用借用构造函数来继承父类通过this声明的属性和方法在之子类的实例属性上。

5.1 实现

function Father(...arr) {
  this.some = '父类属性';
  this.params = arr;
}
Father.prototype.someFn = function() {
  console.log(1);
}
Father.prototype.someValue = '2';
function Son(fatherParams, ...sonParams) {
  // 借用构造函数继承父类this什么的属性和方法到子类实例属性上
  Father.call(this, ...fatherParams);
  this.text = '子类属性';
  this.sonParams = sonParams;
}
// 原型链继承,将`this`和`prototype`声明的属性/方法继承至子类的`prototype`上
Son.prototype = new Father('xxxxx');
var fatherParams = [];
var sonParams = [];
var sonInstance = new Son(fatherParams, ...sonParams);

5.2 优点

1、解决原型链继承父类this声明的属性或者方法被共享的问题。

2、解决借用构造函数解决不能继承父类prototype对象上的属性/方法问题。

5.3 缺点

1、调用了父类函数两次,造成一定的性能问题。

2、因调用两次父类,导出父类通过this声明的属性和方法被生成两份的问题。

3、原型链上下文丢失,子类和父类通过prototype声明的属性和方法都存在与子类prototype上。

六、原型式继承

6.1 实现

function cloneObj(obj) {
  function F(){};
  // 将被继承的对象作为空函数的prototype
  F.prototype = obj;
  // 返回new期间创建的新对象,此对象的原型为被继承的对象,
  // 通过原型链查找可以拿到被继承对象的属性
  return new F();
}

6.2 优点

1、兼容性好,最简单的对象继承。

6.3 缺点

1、多少实例共享被继承的属性,存在被篡改的情况,不能传递参数。

七、寄生式继承(继承过程封装)

创建一个仅用于封装继承过程的函数,改函数在内部已某种方式类增强对象,最后返回对象。在原型式继承的基础上进行增强对象。

7.1 实现

function createAnother(original){
 var clone = cloneObject(original); // 继承一个对象 返回新函数
 // do something 以某种方式来增强对象
 clone.some = function(){}; // 方法
 clone.obkoro1 = '封装继承过程'; // 属性
 return clone; // 返回这个对象
}

7.2 优点

1、兼容性好,最简单的对象继承。

7.3 缺点

1、多少实例共享被继承的属性,存在被篡改的情况,不能传递参数。

八、寄生组合式继承(call+寄生式封装)

1、使用借用构造函数来继承父类this声明的属性和方法。2、使用寄生式继承来设置父类prototype为子类prototype的原型来继承父类的属性和方法。

8.1 实现

function Father(...arr) {
  this.some = '父类属性';
  this.params = arr;
}
Father.prototype.someFn = function() {
  console.log(1);
}
Father.prototype.someValue = '2';
function Son() {
  Father.call(this, 'xxxx');
  this.text = '2222';
}
function inhertPro(son, father){
  // 原型式继承
  var fatherPrototype = Object.create(father.prototype);
  // 设置Son.prototype的原型是Father.prototype
  son.prototype = fatherPrototype;
  // 修正constructor 指向
  // constructor的作用:返回创建实例对象的Object构造函数的引用。
  // 在这里保持constructor指向的一致性
  son.prototype.constructor = son;
}
inhertPro(Son, Father);
var sonInstance = new Son();

8.2 优点

1、寄生组合式继承是当前最成熟的继承方法,也是先也常用的继承方法,在大多数Js框架中都是用这个作为继承方案。

寄生组合式继承相对组合继承的优点:

1、只调用了父类构造函数一次,节约了性能。

2、避免生成了不必要的属性。

3、使用原型式继承保证了原型链上下文不变,子类的prototype只有子类通过prototype声明的属性和方法,父类的prototype只有父类通过prototype声明的属性和方法。

九、ES6-extends继承

9.1 实现

ES6可以用过extends关键字实现继承,这比通过ES5的修改原型链实现继承,要清晰和方法很多。

class Point{}
class ColorPoint extends Point{}

9.2 注意

子类必须在constructor方法中代用super方法,否则新建实例将会报错,这是因为子类自己的this对象,必须先通过父类的构造函数完成塑性,得到父类的属性和方法,然后对其加工,加上子类自己的属性和方法。如果不调用super方法,子类将得不到this对象。如果没有定义constructor方法,这个方法会被默认的添加。

9.3 转换

ES6继承的原理跟寄生组合式继承是一样的。优缺点也相仿。

把ES6的代码装换为ES5 https://www.babeljs.cn/repl

转换前:

class Point{}
class ColorPoint extends Point{}

转换后:

这样回答继承可能面试官更满意

转换的结果核心代码如下:用于子类的prototype继承父类的prototype方法。

function _inherits(subClass, superClass) {
  if (typeof superClass !== "function" && superClass !== null) {
    throw new TypeError("Super expression must either be null or a function");
  }
  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: {
      value: subClass, writable: true, configurable: true 
    }
  });
  if (superClass) _setPrototypeOf(subClass, superClass);
}

9.4 区别

ES5的继承实质是先创建子类的实例对象this,然后将父类的方法添加到this上。

ES6的继承实质是先将父类实例对象的方法和属性加到this上面,然后在用子类的构造函数修改this。

参考

JS基础-深入浅出继承
JavaScript高级程序设计

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript的面向对象(二)
Nov 09 Javascript
javascript 屏蔽鼠标键盘的几段代码
Jan 02 Javascript
修改好的jquery滚动字幕效果实现代码
Jun 22 Javascript
jQuery Tab插件 用于在Tab中显示iframe,附源码和详细说明
Jun 27 Javascript
JS画线(实例代码)
Nov 20 Javascript
js实现楼层效果的简单实例
Jul 15 Javascript
详解Angular4中路由Router类的跳转navigate
Jun 09 Javascript
JS实现上传图片的三种方法并实现预览图片功能
Jul 14 Javascript
AngularJS实现表单元素值绑定操作示例
Oct 11 Javascript
js循环map 获取所有的key和value的实现代码(json)
May 09 Javascript
Web安全之XSS攻击与防御小结
Dec 13 Javascript
vue+element_ui上传文件,并传递额外参数操作
Dec 05 Vue.js
jquery实现弹窗(系统提示框)效果
Dec 10 #jQuery
微信小程序 this.triggerEvent()的具体使用
Dec 10 #Javascript
jQuery实现消息弹出框效果
Dec 10 #jQuery
jQuery实现弹出层效果
Dec 10 #jQuery
javascript实现弹出层效果
Dec 10 #Javascript
element表格翻页第2页从1开始编号(后端从0开始分页)
Dec 10 #Javascript
微信小程序实现注册登录功能(表单校验、错误提示)
Dec 10 #Javascript
You might like
理解php原理的opcodes(操作码)
2010/10/26 PHP
采用thinkphp自带方法生成静态html文件详解
2014/06/13 PHP
Web开发者必备的12款超赞jQuery插件
2010/12/03 Javascript
jQuery.clean使用方法及思路分析
2013/01/07 Javascript
使用jQuery重置(reset)表单的方法
2014/05/05 Javascript
javascript学习笔记(三)BOM和DOM详解
2014/09/30 Javascript
JavaScript定义类和对象的方法
2014/11/26 Javascript
JavaScript实现16进制颜色值转RGB的方法
2015/02/09 Javascript
javascript封装 Cookie 应用接口
2015/08/07 Javascript
jQuery插件AjaxFileUpload实现ajax文件上传
2016/05/05 Javascript
jQuery easyUI datagrid 增加求和统计行的实现代码
2016/06/01 Javascript
浅谈vuejs实现数据驱动视图原理
2018/02/23 Javascript
vue自动化表单实例分析
2018/05/06 Javascript
JavaScript数据结构与算法之二叉树插入节点、生成二叉树示例
2019/02/21 Javascript
vue自定义标签和单页面多路由的实现代码
2020/05/03 Javascript
node.js +mongdb实现登录功能
2020/06/18 Javascript
python使用Berkeley DB数据库实例
2014/09/26 Python
Python使用Selenium+BeautifulSoup爬取淘宝搜索页
2018/02/24 Python
Python创建普通菜单示例【基于win32ui模块】
2018/05/09 Python
详解python的sorted函数对字典按key排序和按value排序
2018/08/10 Python
python多项式拟合之np.polyfit 和 np.polyld详解
2020/02/18 Python
python实现逆滤波与维纳滤波示例
2020/02/26 Python
django中ImageField的使用详解
2020/12/21 Python
Css3新特性应用之视觉效果实例
2016/12/12 HTML / CSS
html5 canvas实现圆形时钟代码分享
2013/12/25 HTML / CSS
自我评价的写作规则
2014/01/06 职场文书
寒假实习自荐信
2014/01/26 职场文书
激情洋溢的毕业生就业求职信
2014/03/15 职场文书
学校安全教育月活动总结
2014/07/07 职场文书
2015年全国爱眼日活动小结
2015/02/27 职场文书
政府会议通知范文
2015/04/15 职场文书
2015年高三年级组工作总结
2015/07/21 职场文书
2016新年晚会开场白
2015/12/03 职场文书
李白经典诗之一:全文无一“月”字,却句句有月
2019/07/12 职场文书
python实现股票历史数据可视化分析案例
2021/06/10 Python
动作冒险《Hell Is Us》将采用虚幻5 消灭怪物探索王国
2022/04/13 其他游戏