2021.06.17(理解js中的深拷贝和浅拷贝)
作者:互联网
基本数据类型:赋值,赋值之后两个变量互不影响
引用数据类型:赋址,两个变量具有相同的引用,指向同一个对象,相互之间有影响
<script> // 基本类型 var a = 100; var b = a; a = 200; console.log(a, b); // 200, 100 ,a b指向不同的数据 // 引用类型指向同一份数据 var a = { c: 1000 }; var b = a; a.c = 2000; console.log(a.c, b.c); // 2000, 2000 全是2000,a b指向同一份数据 </script>
通常在开发中并不希望改变变量 a 之后会影响到变量 b,这时就需要用到浅拷贝和深拷贝。
浅拷贝
创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,
所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
<script> function cloneShallow(source) { var target = {}; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } return target; } var a1 = { b: { c: {} } }; var a2 = cloneShallow(a1); // 浅拷贝 a2.b.c = { d: "1" }; console.log("a1---", a1); //{b:{c:{d:"1"}}} console.log("a2---", a2); //{b:{c:{d:"1"}}} var a5 = { b: { d: [1,2] } }; var a6 = cloneShallow(a5); // 浅拷贝 a6.b.d = [3,4]; console.log("a5---", a5); //{b:{d[3,4])) console.log("a6---", a6); //{b:{d[3,4])) // 注意:当object只有一层的时候,是深拷贝,例如如下: var a3 = { b:'9'}; var a4 = cloneShallow(a3); a4.b = '10'; console.log("a3---", a3); //{b:'9'} console.log("a4---", a4); //{b:'10'} </script>
Object.assign()
Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。注意,Object.assgin() 进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。
Object.assign(target, ...sources)
Array.prototype.concat()
Array.prototype.slice()
...obj 展开运算符
深拷贝
深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。拷贝前后两个对象互不影响
<script> function isObject(obj) { return typeof obj === "object" && obj != null; } function cloneDeep(source) { if (!isObject(source)) return source; // 非对象返回自身 var target = Array.isArray(source) ? [] : {}; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { if (isObject(source[key])) { target[key] = cloneDeep(source[key]); // 注意这里 } else { target[key] = source[key]; } } } return target; } var obj = { title: "study", list: ["1", "2", "3"], }; var obj2 = cloneDeep(obj); obj2.title = "play"; obj2.list = ["3", "4"]; console.log("obj", obj); //title: "style",list: ["1", "2", "3"] console.log("obj2", obj2); //title: "play",list: ["3", "4"] </script>
JSON.parse(JSON.stringify(object))
JSON.stringify():将对象转成 JSON 字符串。
JSON.parse():将字符串解析成对象。
通过 JSON.parse(JSON.stringify()) 将 JavaScript 对象转序列化(转换成 JSON 字符串),
再将其还原成 JavaScript 对象,一去一来我们就产生了一个新的对象,而且对象会开辟新的栈,从而实现深拷贝。
注意
注意,该方法的局限性:
1、不能存放函数或者 Undefined,否则会丢失函数或者 Undefined;
2、不要存放时间对象,否则会变成字符串形式;
3、不能存放 RegExp、Error 对象,否则会变成空对象;
4、不能存放 NaN、Infinity、-Infinity,否则会变成 null;
5、……更多请自行填坑,具体来说就是 JavaScript 和 JSON 存在差异,两者不兼容的就会出问题。
函数库 Lodash
cloneDeep() 方法
npm i --save lodash var _ = require('lodash'); var objects = [{ 'a': 1 }, { 'b': 2 }]; var deep = _.cloneDeep(objects); console.log(deep[0] === objects[0]); // => false
2021-06-17 11:18:29
标签:2021.06,17,对象,source,key,var,console,拷贝 来源: https://www.cnblogs.com/zhenggc99/p/14892672.html