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 相关文章推荐
JavaScript四种调用模式和this示例介绍
Jan 02 Javascript
js限制文本框只能输入数字方法小结
Jun 16 Javascript
纯js代码制作的网页时钟特效【附实例】
Mar 30 Javascript
全面了解JavaScirpt 的垃圾(garbage collection)回收机制
Jul 11 Javascript
基于Vuejs的搜索匹配功能实现方法
Mar 03 Javascript
angular 组件通信的几种实现方式
Jul 13 Javascript
Vue之mixin全局的用法详解
Aug 22 Javascript
详解vuex之store源码简单解析
Jun 13 Javascript
详解elementui之el-image-viewer(图片查看器)
Aug 30 Javascript
VUE table表格动态添加一列数据,新增的这些数据不可以编辑(v-model绑定的数据不能实时更新)
Apr 03 Javascript
javascript设计模式 ? 观察者模式原理与用法实例分析
Apr 22 Javascript
javascript实现固定侧边栏
Feb 09 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对XML的操作详解
2013/06/07 PHP
PHP获取QQ达人QQ信息的方法
2015/03/05 PHP
php使用Jpgraph绘制柱形图的方法
2015/06/10 PHP
yii分页组件用法实例分析
2015/12/28 PHP
浅析Laravel5中队列的配置及使用
2016/08/04 PHP
php基于session锁防止阻塞请求的方法分析
2017/08/07 PHP
在JavaScript中判断整型的N种方法示例介绍
2014/06/18 Javascript
js实现按钮控制图片360度翻转特效的方法
2015/02/17 Javascript
JS实现文档加载完成后执行代码
2015/07/09 Javascript
JavaScript 继承详解(六)
2016/10/11 Javascript
浅析JavaScript动画模拟拖拽原理
2016/12/09 Javascript
JS区分Object与Aarry的六种方法总结
2017/02/27 Javascript
搭建一个Koa后端项目脚手架的方法步骤
2019/05/30 Javascript
vue项目中将element-ui table表格写成组件的实现代码
2019/06/12 Javascript
JS实现打字游戏
2019/12/17 Javascript
Python实现LRU算法的2种方法
2015/06/24 Python
python 二分查找和快速排序实例详解
2017/10/13 Python
对Python中9种生成新对象的方法总结
2018/05/23 Python
浅谈DataFrame和SparkSql取值误区
2018/06/09 Python
Python3按一定数据位数格式处理bin文件的方法
2019/01/24 Python
解决python有时候import不了当前的包问题
2019/08/28 Python
Python 程序员必须掌握的日志记录
2020/08/17 Python
CSS3的transition和animation的用法实例介绍
2014/08/20 HTML / CSS
大学生农村教师实习自我鉴定
2013/09/21 职场文书
工程造价与管理专业应届生求职信
2013/11/23 职场文书
师范教师毕业鉴定
2014/01/13 职场文书
教师现实表现材料
2014/02/14 职场文书
经理助理岗位职责
2014/03/05 职场文书
超市开店计划书
2014/04/26 职场文书
工作说明书格式
2014/07/29 职场文书
工作所在部门证明
2014/09/21 职场文书
2014年仓库管理工作总结
2014/12/17 职场文书
2015年审计人员工作总结
2015/05/26 职场文书
大学体育课感想
2015/08/10 职场文书
导游词之太行山青龙峡
2020/01/14 职场文书
Python基础之条件语句详解
2021/06/16 Python