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 相关文章推荐
Ext对基本类型的扩展 ext,extjs,format
Dec 25 Javascript
JavaScript 判断日期格式是否正确的实现代码
Jul 04 Javascript
JS获取网页属性包括宽、高等等
Apr 03 Javascript
js函数定时器实现定时读取系统实时连接数
Apr 30 Javascript
js选择器全面解析
Jun 27 Javascript
解析利用javascript如何判断一个数为素数
Dec 08 Javascript
详解React中的组件通信问题
Jul 31 Javascript
基于IView中on-change属性的使用详解
Mar 15 Javascript
使用puppeteer爬取网站并抓出404无效链接
Dec 20 Javascript
利用百度echarts实现图表功能简单入门示例【附源码下载】
Jun 10 Javascript
angularjs1.X 重构controller 的方法小结
Aug 15 Javascript
基于JavaScript实现留言板功能
Mar 16 Javascript
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
php安全开发 添加随机字符串验证,防止伪造跨站请求
2013/02/14 PHP
Thinkphp调用Image类生成缩略图的方法
2015/03/07 PHP
WordPress的主题编写中获取头部模板和底部模板
2015/12/28 PHP
jQuery常用操作方法及常用函数总结
2014/06/19 Javascript
JS打开新窗口防止被浏览器阻止的方法
2015/01/03 Javascript
js简单工厂模式用法实例
2015/06/30 Javascript
javascript字符串循环匹配实例分析
2015/07/17 Javascript
js实现用户离开页面前提示是否离开此页面的方法(包括浏览器按钮事件)
2015/07/18 Javascript
JS正则表达式之非捕获分组用法实例分析
2016/12/28 Javascript
ExtJs的Ext.Ajax.request实现waitMsg等待提示效果
2017/06/14 Javascript
JS实现预加载视频音频/视频获取截图(返回canvas截图)
2017/10/09 Javascript
解决Jquery下拉框数据动态获取的问题
2018/01/25 jQuery
React Native自定义控件底部抽屉菜单的示例
2018/02/08 Javascript
vue filter 完美时间日期格式的代码
2019/08/14 Javascript
原生JavaScript实现贪吃蛇游戏
2020/11/04 Javascript
[01:07:46]完美世界DOTA2联赛循环赛 Magma vs IO BO2第二场 11.01
2020/11/02 DOTA
使用C语言来扩展Python程序和Zope服务器的教程
2015/04/14 Python
Python使用dis模块把Python反编译为字节码的用法详解
2016/06/14 Python
基于pycharm导入模块显示不存在的解决方法
2018/10/13 Python
python实现Excel文件转换为TXT文件
2019/04/28 Python
如何用Python来搭建一个简单的推荐系统
2019/08/07 Python
PyCharm 2019.3发布增加了新功能一览
2019/12/08 Python
浅谈python的elementtree模块处理中文注意事项
2020/03/06 Python
python连接mysql数据库并读取数据的实现
2020/09/25 Python
Numpy数组的广播机制的实现
2020/11/03 Python
python制作微博图片爬取工具
2021/01/16 Python
Supersmart英国:欧洲市场首批食品补充剂供应商之一
2018/05/05 全球购物
实用求职信范文分享
2013/12/25 职场文书
遗嘱公证书标准样本
2014/04/08 职场文书
出生医学证明书
2014/09/15 职场文书
招商引资工作汇报
2014/10/28 职场文书
学校推普周活动总结
2015/05/07 职场文书
2015年环保局工作总结
2015/05/22 职场文书
预备党员党支部意见
2015/06/02 职场文书
大学生受助感言
2015/08/01 职场文书
ant design vue的form表单取值方法
2022/06/01 Vue.js