JS面试题中深拷贝的实现讲解


Posted in Javascript onMay 07, 2020

在面试中你是否遇到过如下场景:

Q:小朋友,你是否了解如何拷贝一个对象?

R:此时,机智的你可能会想到

Object.assign({}, obj);

Q:那如何深拷贝一个对象呢?

R:机智的你

JSON.parse(JSON.stringify(obj));

Q:使用stringify这种方式有何弊端?

  1. 性能问题,stringify再解析其实需要耗费较多时间,特别是数据量大的时候。
  2. 一些类型无法拷贝,例如函数(不输出),正则(输出空对象),时间对象(输出时间字符串),Undefiend(不输出)
  3. 遇到循环引用的对象会出错
  4. 同层(非同层)同引用的问题,理论下两个key对应的val如果指向同一个对象,拷贝也应该指向一个相同新地址才对

Q:那你能自己实现个深拷贝函数?

R:如下:

const deepClone = (obj) => {
 // 非引用类型及函数将直接返回
 if (!obj || typeof obj !== 'object') return obj;

 // 特殊的引用类型处理
 switch(Object.prototype.toString.call(obj).slice(8, -1)) {
  case 'Date': 
   return new Date(obj);
   break;
  case 'RegExp': 
   return new RegExp(obj);
   break;
  case 'String': 
   return new String(obj);
   break;
  case 'Number': 
   return new Number(obj);
   break;
  case 'Boolean': 
   return new Boolean(obj);
   break;
 }

 const result = obj instanceof Array ? [] : {};

 for (let propName in obj) {
  if (obj.hasOwnProperty(propName)) {
   result[propName] = deepClone(obj[propName]);
  }
 }

 return result;
}

优点:实现了大多数数据类型的拷贝,所有非引用类型及引用类型的String Number Boolean Function Array Date RegExp

缺点:未考虑一些特殊的引用类型如Error Math Symbol Map Set JSON,函数属于引用拷贝,未解决循环引用的问题

Q:如何解决循环引用?

R:将父层级的数据缓存对比(可以顺带解决同层(非同层)同引用的问题)

const deepClone = (obj) => {
 // 非引用类型及函数将直接返回
 if (!obj || typeof obj !== 'object') return obj;

 // 特殊的引用类型处理
 switch (Object.prototype.toString.call(obj).slice(8, -1)) {
  case 'Date':
   return new Date(obj);
   break;
  case 'RegExp':
   return new RegExp(obj);
   break;
  case 'String':
   return new String(obj);
   break;
  case 'Number':
   return new Number(obj);
   break;
  case 'Boolean':
   return new Boolean(obj);
   break;
 }

 const map = deepClone.map = deepClone.map || new Map();

 // 使用map结构可以不必循环缓存,提高效率
 if (map.get(obj)) {
  return map.get(obj);
 }

 const result = obj instanceof Array ? [] : {};

 // 如果仔细观察可以发现解决了同层同引用的问题
 map.set(obj, result);

 for (let propName in obj) {
  if (obj.hasOwnProperty(propName)) {
   result[propName] = deepClone(obj[propName]);
  }
 }

 return result;
}

Q:为什么函数还是指向原来的函数,而不创建新函数?

R:理论下函数也可以通过new Function(code)来创建新的函数,但是如果遇到闭包函数,我们无法得到原函数的外层定义的变量及其原有作用域链,这些在JS词法解析时完成的步骤我们无法得知,所有只能引用原函数比较好。

Sum: 上面实现的缺点主要是没有完全覆盖特殊引用类型,但其实我们平时应该不会遇到那些类型,所以可以凑合使用。如果还有其它的问题没有考虑到或者有出错的,希望大家可以帮忙指出。

以上就是JS面试题中深拷贝的实现讲解的详细内容,更多关于JS深拷贝的实现的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
js用图作提交按钮或超连接
Mar 26 Javascript
jquery each()源代码
Feb 14 Javascript
jQuery中的height innerHeight outerHeight区别示例介绍
Jun 15 Javascript
JavaScript中获取样式的原生方法小结
Oct 08 Javascript
node.js中的fs.rmdirSync方法使用说明
Dec 16 Javascript
JavaScript数组去重的五种方法
Nov 05 Javascript
基于javascript编写简单日历
May 02 Javascript
JavaScript代码性能优化总结篇
May 15 Javascript
js轮播图透明度切换(带上下页和底部圆点切换)
Apr 27 Javascript
Bootstrap Table使用整理(二)
Jun 09 Javascript
Node.js实现连接mysql数据库功能示例
Sep 15 Javascript
jQuery中的for循环var与let的区别
Apr 21 jQuery
javascript 代码是如何被压缩的示例代码
May 06 #Javascript
Layui弹框中数据表格中可双击选择一条数据的实现
May 06 #Javascript
Vue SSR 即时编译技术的实现
May 06 #Javascript
深入webpack打包原理及loader和plugin的实现
May 06 #Javascript
将Vue组件库更换为按需加载的方法步骤
May 06 #Javascript
让IDE识别webpack的别名alias的实现方法
May 06 #Javascript
JS 设计模式之:工厂模式定义与实现方法浅析
May 06 #Javascript
You might like
Linux编译升级php的详细方法
2013/11/04 PHP
PHP设计模式之观察者模式(Observer)详细介绍和代码实例
2014/04/08 PHP
PHP实现的简单网络硬盘
2015/07/29 PHP
win7系统配置php+Apache+mysql环境的方法
2015/08/21 PHP
“不能执行已释放的Script代码”错误的原因及解决办法
2007/09/09 Javascript
CSS常用网站布局实例
2008/04/03 Javascript
jQuery EasyUI中对表格进行编辑的实现代码
2010/06/10 Javascript
JS验证身份证有效性示例
2013/10/11 Javascript
jquery实现当滑动到一定位置时固定效果
2014/06/17 Javascript
JS截取字符串实例详解
2015/11/24 Javascript
JavaScript对象数组排序函数及六个用法
2015/12/23 Javascript
Ionic默认的Tabs模板使用实例
2016/08/29 Javascript
jQuery实现对网页节点的增删改查功能示例
2017/09/18 jQuery
JS原型继承四步曲及原型继承图一览
2017/11/28 Javascript
解决vuecli3.0热更新失效的问题
2018/09/19 Javascript
JavaScript遍历查找数组中最大值与最小值的方法示例
2019/05/24 Javascript
JS实现随机抽取三人
2019/11/06 Javascript
JS实现联想、自动补齐国家或地区名称的功能
2020/07/07 Javascript
python如何生成网页验证码
2018/07/28 Python
深入理解Python异常处理的哲学
2019/02/01 Python
Python Pandas 箱线图的实现
2019/07/23 Python
10张动图学会python循环与递归问题
2021/02/06 Python
美国最大点评网站:Yelp
2018/02/14 全球购物
extern是什么意思
2016/03/10 面试题
JAVA程序设计笔试题面试题一套
2015/07/28 面试题
公司中秋节活动方案
2014/02/12 职场文书
公司活动方案范文
2014/03/06 职场文书
婚礼主持结束词
2014/03/13 职场文书
小学二年级评语
2014/04/21 职场文书
勾股定理课后反思
2014/04/26 职场文书
社区安全生产月活动总结
2014/07/05 职场文书
小学生教师节演讲稿
2014/09/03 职场文书
医药公司采购员岗位职责
2014/09/12 职场文书
2015年健康教育工作总结
2015/04/10 职场文书
2015年宣传思想工作总结
2015/05/22 职场文书
2015年音乐教研组工作总结
2015/07/22 职场文书