大家都知道,js的对象是引用类型,如果直接var obj2 = obj,obj2和obj是共享同一个对象实体的,这往往不是我们想要的结果。

官方并没有给出通用的对象克隆方法:

我们给出以下几种写法:

1.通用对象克隆:

function clone(obj, hash = new WeakMap()) {
// 解决循环引用
if (hash.has(obj)) {
return hash.get(obj)
}
let temp = null;
if (obj instanceof Array) {
// 特殊处理数组对象类型
temp = []
hash.set(obj, temp)
obj.forEach(item => {
temp.push(clone(item, hash));
})
} else if (obj instanceof RegExp) {
// 特殊处理正则对象类型
const { source, global, ignoreCase, multiline } = obj;
let flags = '';
if (global) flags += 'g';
if (ignoreCase) flags += 'i';
if (multiline) flags += 'm';
temp = new RegExp(source, flags);
} else if (obj instanceof Date) {
// 特殊处理时间对象类型
temp = new Date(obj.getTime());
} else if (typeof obj === 'object') {
// 处理普通对象类型
// 以obj的原型为原型,构造一个新对象
temp = Object.create(obj.__proto__);
hash.set(obj, temp)
} else {
temp = obj;
}
// 任何对象类型,都遍历递归自身的属性
if (typeof obj === 'object') {
for (let [key, val] of Object.entries(obj)) {
temp[key] = clone(val, hash);
}
}
return temp;
}

遇到数组对象类型、正则对象类型、时间对象类型、普通对象类型都需要有自己的特殊,最后他们都需要遍历递归他们自身的属性

原始类型(包括Symbol)纯复制就可以了

函数做的浅拷贝(因为如果拷贝函数,只能用eval这个危险的工具了,所以这里函数仅作浅克隆,lodash的cloneDeep对函数也是浅克隆处理)

推荐阅读:https://juejin.im/post/5b235b726fb9a00e8a3e4e88

ps:这里还有一些坑,无法克隆 Error 对象,无法克隆原型,无法克隆不可枚举的属性.... 不过这个深克隆已经可以覆盖百分之99的场景了!!

2.JSON对象序列化方法

深拷贝,但是有一大堆坑(推荐阅读:https://juejin.im/post/5abb55ee6fb9a028e33b7e0a):

基础的5个大坑:

1. 函数不能拷贝

2. Symbol不能拷贝

4. undefined不能拷贝

5. 正则拷贝后变成普通对象

6. 循环引用的对象会报错

7. 数组的属性丢失

8. 数组里面的undefined会变成null

9. 会抛弃对象的constructor

。。。。估计还有很多我没想到的

let a = { age: undefined, sex: Symbol('male'), jobs: function() {}, name: 'yck' } 
let b = JSON.parse(JSON.stringify(a)) console.log(b) // {name: "yck"}

正常使用:

var obj = {a:1,b:2}
var newObj = JSON.parse(JSON.stringify(obj));

3.dom元素的复制——cloneNode

let div = document.getElementById('box');
let box2 = div.cloneNode(true);

4.es6新方法——Object.assign

浅拷贝

var obj = {a:1,b:2}
var newObj = Object.assign({}, obj);

5. MessageChannel的方法

异步的深克隆,但是无法克隆function 、Symbol

let obj = {a: 1,b: 2}

let {port1, port2} = new MessageChannel();
port2.onmessage = ev => console.log(ev.data)
port2.postMessage(obj)

总结:日常使用还是推荐用lodash的cloneDeep

最新文章

  1. 【bzoj1010】 HNOI2008—玩具装箱toy
  2. 【转】Unity3D中Layers和LayerMask解析
  3. 【转】JNI 对象处理
  4. swing——JFrame基本操作
  5. [翻译] C++ STL容器参考手册(第二章 <deque>)
  6. js 推断 当页面无法回退时(history.go(-1)),关闭网页
  7. [C#基础] 继承
  8. Effective Objective-C 2.0 笔记三(Literal Syntax简写语法)
  9. android:editable is deprecated: Use an <EditText> to make it editable
  10. mongodb 分片群集(sharding cluster)
  11. ShoneSharp语言(S#)的设计和使用介绍系列(3)— 修炼工具
  12. Python sort后赋值 操作陷阱
  13. 从零打卡leetcode之day 1--两数之和
  14. AX2009 批处理作业中使用多线程---批量捆绑
  15. Django 2.11 静态页面404 解决
  16. 新eclipse 打开就版本的工作空间提示:
  17. Luogu3804 【模板】后缀自动机(后缀自动机)
  18. Unity PC端发布失败解决办法
  19. 基于ubuntu搭建 WordPress 个人博客
  20. 笔记本无密码连接wifi

热门文章

  1. Linux内核分析— —构造一个简单的Linux系统MenuOS(20135213林涵锦)
  2. [福大软工] Z班 评测作业对应表
  3. HDOJ2032_杨辉三角
  4. Maven相关问题解决.docx
  5. JMeter性能测试基础 (4)-使用JMeter录制测试脚本
  6. [转帖]知乎专栏:正确使用 Docker 搭建 GitLab 只要半分钟
  7. Lodop打印二维码内容长度不同如何大小相同
  8. mysql DDL&DML 语言
  9. John's trip POJ - 1041(这题数据有点水)
  10. importlib 模块