js浅拷贝和深拷贝
浅拷贝是拷贝一层,深层次的对象级别的就拷贝引用;深拷贝是拷贝多层,每一级别的数据都会拷贝出来;
理解:浅拷贝的时候如果数据是基本数据类型,那么就如同直接赋值那种,会拷贝其本身;
如果除了基本数据类型之外还有一层对象,那么对于浅拷贝而言就只能拷贝其引用,对象的改变会反应到拷贝对象上;
但是深拷贝就会拷贝多层,即使是嵌套了对象,也会都拷贝出来。
即浅拷贝只拷贝第一层的数据,开辟新的内存空间,下面的层次还是共用内存空间;
而深拷贝每一层都是新的内存空间,独立起来的
浅拷贝的常用方法:
1.ES6的扩展运算符
let obj = { name:“dilireba” } let newObj = {…obj} obj.name = “liqin” console.log(obj,newObj) //{ name: ‘liqin’ } { name: ‘dilireba’ }
2.ES6中的Object.assign方法
var obj1 = { a: "hello", b: { a: "hello", b: 21} }; var cloneObj1= Object.assign({}, obj1); cloneObj1.a = "changed"; cloneObj1.b.a = "changed"; console.log(obj1.a); //hello console.log(obj.b.a); // "changed"
改变cloneObj1.a的时候,因为是浅拷贝在第一层,互不影响,所以obj1.a还是hello
改变cloneObj1.b.a的时候,是在第二层的,与obj1.b.a共用一个内存空间,所以obj1.b.a是新的数据changed
深拷贝常用方法:
1.转成 JSON 再转回来
JSON.parse(JSON.stringify(obj))
缺点:
抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。
只有可以转成JSON
格式的对象才可以这样用,像function
没办法转成JSON,
如果你拷贝的对象中存在函数,函数会消失
var obj1 = { fun: function(){ console.log(123) } }; var obj2 = JSON.parse(JSON.stringify(obj1)); console.log(typeof obj1.fun); // 'function' console.log(typeof obj2.fun); // 'undefined' <-- 没复制
2.递归拷贝
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) ? [] : {}; arguments.callee(prop, obj[i]); } else { obj[i] = prop; } } return obj; } var str = {}; var obj = { a: {a: "hello", b: 21} }; deepClone(obj, str); console.log(str.a);