摘要:但是进行的是浅拷贝,拷贝的是属性值。对象展开符深拷贝的实现方式手动复制转成再转回来只有可以转成格式的对象才可以这样用,像没办法转成沒被改到使用方法避免相互引用对象导致死循环,如的情况四参考关于的浅拷贝和深拷贝
一、理解
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。二、浅拷贝与深拷贝
浅拷贝:赋值时,基本数据类型按值传递,对象按引用传递
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);四、参考
【1】关于JavaScript的浅拷贝和深拷贝
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/100164.html
摘要:在中可以通过添加一个参数来实现递归,调用就可以实现一个深拷贝。利用序列化实现一个深拷贝 在JavaScript中,对于Object和Array这类引用类型值,当从一个变量向另一个变量复制引用类型值时,这个值的副本其实是一个指针,两个变量指向同一个堆对象,改变其中一个变量,另一个也会受到影响。 这种拷贝分为两种情况:拷贝引用和拷贝实例,也就是我们说的浅拷贝和深拷贝 浅拷贝(shallow...
摘要:引用类型值引用类型值是保存在堆内存中的对象,变量保存的只是指向该内存的地址,在复制引用类型值的时候,其实只复制了指向该内存的地址。 前言 要理解 JavaScript中浅拷贝和深拷贝的区别,首先要明白JavaScript的数据类型。JavaScript有两种数据类型,基础数据类型和引用数据类型。js的基本类型:undefined,null,string,boolean,number,s...
摘要:说明外层数组拷贝的是实例说明元素拷贝是引用深拷贝在堆中重新分配内存,并且把源对象所有属性都进行新建拷贝,拷贝后的对象与原来的对象完全隔离,互不影响。中的方法可以实现深拷贝,源码原理也是递归使用浅拷贝。 1.浅拷贝 当把数组或对象简单赋值给其他变量的时候,实际上进行的是浅拷贝,浅拷贝是拷贝引用,只是将拷贝后的引用指向同一个对象实例,彼此间的操作还会互相影响。 分为两种情况:直接拷贝源对象...
摘要:而大多数实际项目中,我们想要的结果是两个变量初始值相同互不影响。所以就要使用到拷贝分为深浅两种深浅拷贝的区别浅拷贝只复制一层对象的属性,而深拷贝则递归复制了所有层级。 为什么会用到浅拷贝和深拷贝 首先来看一下如下代码 let a = b = 2 a = 3 console.log(a) console.log(b) let c = d = [1,2,3] let e = f = {a:...
摘要:而大多数实际项目中,我们想要的结果是两个变量初始值相同互不影响。所以就要使用到拷贝分为深浅两种深浅拷贝的区别浅拷贝只复制一层对象的属性,而深拷贝则递归复制了所有层级。 为什么会用到浅拷贝和深拷贝 首先来看一下如下代码 let a = b = 2 a = 3 console.log(a) console.log(b) let c = d = [1,2,3] let e = f = {a:...
阅读 2537·2023-04-25 20:05
阅读 2873·2023-04-25 17:56
阅读 2174·2021-10-14 09:49
阅读 2655·2019-08-29 15:10
阅读 2879·2019-08-29 12:25
阅读 399·2019-08-28 18:23
阅读 721·2019-08-26 13:26
阅读 1348·2019-08-23 18:21