一、理解
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
二、浅拷贝与深拷贝
-
浅拷贝:赋值时,基本数据类型按值传递,对象按引用传递
var a = 25; var b = a; b = 18; console.log(a);//25 console.log(b);//18 // b的修改并不会影响到a,因为它们是基本类型数据
var obj1 = { a: 10, b: 20, c: 30 }; var obj2 = obj1; obj2.b = 100; console.log(obj1); // { a: 10, b: 100, c: 30 } <-- b 被改到了 console.log(obj2); // { a: 10, b: 100, c: 30 } // obj2修改了b的值,同时obj1的b也会被修改,因为他们根本是同一个对象,这就是所谓的浅拷贝
-
深拷贝:
var obj1 = { a: 10, b: 20, c: 30 }; var obj2 = { a: obj1.a, b: obj1.b, c: obj1.c }; obj2.b = 100; console.log(obj1); // { a: 10, b: 20, c: 30 } <-- b 沒被改到 console.log(obj2); // { a: 10, b: 100, c: 30 }
三、实现方式
-
浅拷贝的实现方式
(1)直接赋值,就是浅拷贝。对象直接复制,则新对象的改变也会修改到旧对象。
(2)Object.assign(target, ...sources)
Object.assign
是ES6
的新函数。Object.assign()
方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是Object.assign()
进行的是浅拷贝,拷贝的是属性值。假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值。var obj = { a: {a: "hello", b: 21} }; var initalObj = Object.assign({}, obj); initalObj.a.a = "changed"; console.log(obj.a.a); // "changed"
(3)对象展开符
...
var obj = [{index: 1, msg: 'one'}, {index: 2, msg: 'two'}]; var obj2 = [...obj]; console.log(obj2); //[{index: 1, msg: 'one'}, {index: 2, msg: 'two'}] obj2.push({index: 3, msg: 'three'}); console.log(obj2); // [{index: 1, msg: 'one'}, {index: 2, msg: 'two'}, {index: 3, msg: 'three'}] console.log(obj); // [{index: 1, msg: 'one'}, {index: 2, msg: 'two'}] obj2[1].msg = 'two again'; console.log(obj2); // [{index: 1, msg: 'one'}, {index: 2, msg: 'two again'}, {index: 3, msg: 'three'}] console.log(obj); // [{index: 1, msg: 'one'}, {index: 2, msg: 'two again'}]
-
深拷贝的实现方式
(1)手动复制var obj1 = { a: 10, b: 20, c: 30 }; var obj2 = { a: obj1.a, b: obj1.b, c: obj1.c };
(2)转成
JSON
再转回来(只有可以转成JSON
格式的对象才可以这样用,像function
没办法转成JSON)var obj1 = { body: { a: 10 } }; var obj2 = JSON.parse(JSON.stringify(obj1)); obj2.body.a = 20; console.log(obj1); // { body: { a: 10 } } <-- 沒被改到 console.log(obj2); // { body: { a: 20 } } console.log(obj1 === obj2); // false console.log(obj1.body === obj2.body); // false
(3)使用
var newObj = Object.create(oldObj)
方法function deepClone(initalObj, finalObj) { var obj = finalObj || {}; for (var i in initalObj) { var prop = initalObj[i]; // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况 if(prop === obj) { continue; } if (typeof prop === 'object') { obj[i] = (prop.constructor === Array) ? [] : Object.create(prop); } else { obj[i] = prop; } } return obj; } var str = {}; var obj = { a: {a: "hello", b: 21} }; deepClone(obj, str);
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。