JS中深拷贝数组、对象、对象数组方法总结
2018-03-31 15:40
531 查看
原文链接:https://blog.csdn.net/helloxiaoliang/article/details/79510366
我们在JS程序中需要进行频繁的变量赋值运算,对于字符串、布尔值等可直接使用赋值运算符 “=” 即可,但是对于数组、对象、对象数组的拷贝,我们需要理解更多的内容。首先,我们需要了解JS的浅拷贝与深拷贝的区别。我们先给出一个数组:
1 数组的深拷贝 对于数组的深拷贝常规的有三种方法:方法一:遍历复制
这种方法简单粗暴,但是利用JS本身的函数我们可以更加便捷地实现这个操作。
方法二:slice()可以参考 W3School 对 slice() 方法的描述:slice() 方法可从已有的数组中返回选定的元素。调用格式为:arrayObject.slice(start,end)方法返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素。该方法并不会修改数组,而是返回一个子数组。在这里我们的思路是直接从数组开头截到尾:
方法三:concat()可以参考 W3School 对 concat() 方法的描述:concat() 方法用于连接两个或多个数组。调用格式为:arrayObject.concat(arrayX,arrayX,......,arrayX)该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。使用这种方法的思路是我们用原数组去拼接一个空内容,放回的便是这个数组的拷贝:
2、对象的深拷贝 对于数组的深拷贝我们有了概念,那么一般对象呢?我们给出一个对象:
而对于对象的深拷贝,没有内置方法可以使用,我们可以自己命名一个函数进行这一操作:
方法二:扩展运算符实现对象的深拷贝var obj = { name: 'FungLeo', sex: 'man', old: '18' }
3、对象数组的深拷贝 如果再考虑更奇葩更复杂的情况,例如我们定义:
或者暴力点转换成json再转换成对象实现对象的深拷贝,但是这种深拷贝有一定的局限性,第一:无法复制函数,第二:原形链没了,对象就是object,所属的类没了。var obj2 = JSON.parse(JSON.stringify(obj));
另附教程:javascript中的深拷贝和浅拷贝? 深拷贝和浅拷贝原文链接:https://blog.csdn.net/helloxiaoliang/article/details/79510366
我们在JS程序中需要进行频繁的变量赋值运算,对于字符串、布尔值等可直接使用赋值运算符 “=” 即可,但是对于数组、对象、对象数组的拷贝,我们需要理解更多的内容。首先,我们需要了解JS的浅拷贝与深拷贝的区别。我们先给出一个数组:
var arr = ["a","b"];现在怎么创建一份arr数组的拷贝呢?直接执行赋值运算吗?我们来看看输出结果
var arrCopy = arr; arrCopy[1] = "c"; arr // => ["a","c"]可以发现对拷贝数组 arrCopy 进行操作时原数组也相应地被改变了,这就是JS的浅拷贝模式。所以我们可以指出对数组、对象、对象数组进行简单赋值运算只是创建了一份原内容的引用,指向的仍然是同一块内存区域,修改时会对应修改原内容,而有时候我们并不需要这种模式,这就需要对内容进行深拷贝。
1 数组的深拷贝 对于数组的深拷贝常规的有三种方法:方法一:遍历复制
1 var arr = ["a", "b"], arrCopy = []; 2 for (var item in arr) arrCopy[item] = arr[item]; 3 arrCopy[1] = "c"; 4 arr // => ["a", "b"] 5 arrCopy // => ["a", "c"]考虑伪多维数组可以写成函数形式:
function arrDeepCopy(source){ var sourceCopy = []; for (var item in source) sourceCopy[item] = typeof source[item] === 'object' ? arrDeepCopy(source[item]) : source[item]; return sourceCopy; }
这种方法简单粗暴,但是利用JS本身的函数我们可以更加便捷地实现这个操作。
方法二:slice()可以参考 W3School 对 slice() 方法的描述:slice() 方法可从已有的数组中返回选定的元素。调用格式为:arrayObject.slice(start,end)方法返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素。该方法并不会修改数组,而是返回一个子数组。在这里我们的思路是直接从数组开头截到尾:
arrCopy = arr.slice(0); arrCopy[1] = "c"; arr // => ["a", "b"] arrCopy // => ["a", "c"]可以看出成功创建了一份原数组的拷贝。
方法三:concat()可以参考 W3School 对 concat() 方法的描述:concat() 方法用于连接两个或多个数组。调用格式为:arrayObject.concat(arrayX,arrayX,......,arrayX)该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。使用这种方法的思路是我们用原数组去拼接一个空内容,放回的便是这个数组的拷贝:
arrCopy = arr.concat(); arrCopy[1] = "c"; arr // => ["a", "b"] arrCopy // => ["a", "c"]
2、对象的深拷贝 对于数组的深拷贝我们有了概念,那么一般对象呢?我们给出一个对象:
var obj = { "a": 1, "b": 2 };同样做测试:
var objCopy = obj; objCopy.b = 3; obj // => { "a": 1, "b": 3 } objCopy // => { "a": 1, "b": 3 }同样,简单的赋值运算只是创建了一份浅拷贝。方法一:遍历复制
而对于对象的深拷贝,没有内置方法可以使用,我们可以自己命名一个函数进行这一操作:
var objDeepCopy = function(source){ var sourceCopy = {}; for (var item in source) sourceCopy[item] = source[item]; return sourceCopy; }但是对于复杂结构的对象我们发现这个函数并不适用,例如:
var obj = { "a": { "a1": ["a11", "a12"], "a2": 1 }, "b": 2 };所以需要进行一点修改,需要我们递归调用浅拷贝就可以了:
var objDeepCopy = function(source){ var sourceCopy = {}; for (var item in source) sourceCopy[item] = typeof source[item] === 'object' ? objDeepCopy(source[item]) : source[item]; return sourceCopy; } var objCopy = objDeepCopy(obj); objCopy.a.a1[1] = "a13"; obj // => { "a": { "a1": ["a11", "a12"], "a2": 1 }, "b": 2 } objCopy // => { "a": { "a1": ["a11", "a13"], "a2": 1 }, "b": 2 }
方法二:扩展运算符实现对象的深拷贝var obj = { name: 'FungLeo', sex: 'man', old: '18' }
var { ...obj2 } = obj
obj.old = '22'
console.log(obj)
console.log(obj2)
3、对象数组的深拷贝 如果再考虑更奇葩更复杂的情况,例如我们定义:
var obj = [{ "a": { "a1": ["a11", "a12"], "a2": 1 }, "b": 2 }, ["c", { "d": 4, "e": 5 }]];这是一个由对象、数组杂合成的奇葩数组,虽然我们平时写程序基本不可能这么折腾自己,但是可以作为一种特殊情况来考虑,这样我们就可以结合之前说的方法去拓展拷贝函数,需要我们递归调用浅拷贝就可以了:
var objDeepCopy = function (source) { var sourceCopy = source instanceof Array ? [] : {}; for (var item in source) { sourceCopy[item] = typeof source[item] === 'object' ? objDeepCopy(source[item]) : source[item]; } return sourceCopy; } var objCopy = objDeepCopy(obj); objCopy[0].a.a1[1] = "a13"; objCopy[1][1].e = "6"; obj // => [{ "a": { "a1": ["a11", "a12"], "a2": 1 }, "b": 2 }, ["c", { "d": 4, "e": 5 }]] objCopy // => [{ "a": { "a1": ["a11", "a13"], "a2": 1 }, "b": 2 }, ["c", { "d": 4, "e": 6 }]]这样它就可以作为一个通用函数替我们进行深拷贝操作了。
或者暴力点转换成json再转换成对象实现对象的深拷贝,但是这种深拷贝有一定的局限性,第一:无法复制函数,第二:原形链没了,对象就是object,所属的类没了。var obj2 = JSON.parse(JSON.stringify(obj));
另附教程:javascript中的深拷贝和浅拷贝? 深拷贝和浅拷贝原文链接:https://blog.csdn.net/helloxiaoliang/article/details/79510366
相关文章推荐
- js数组Array对象常用方法总结
- JS中深拷贝数组、对象、对象数组方法
- JS中深拷贝数组、对象、对象数组方法
- JS中深拷贝数组、对象、对象数组方法(转载)
- JS提交对象数组到服务端的方法总结(C#实例)
- js入门·对象属性方法大总结
- JS 实现 创建类、继承、方法添加、对象克隆、数组封装操作
- js入门·对象属性方法大总结
- js中文本和数组的方法总结
- Js中JSON字符串和对象互转的方法总结
- js入门·对象属性方法大总结
- Map接口及其重要实现类的方法总结:从HashMap中放入,查找,删除一个对象,并将全部value放入到一个数组中;获得HashMap的全部数据
- js克隆对象、数组的常用方法介绍
- json对象与数组以及转换成js对象的方法
- js对象属性方法大总结
- js中数组Array的一些常用方法总结
- jQuery 1.6 源码学习(六)——core.js[6]之jQuery对象/数组操作相关方法
- C#中深拷贝对象的简单方法
- java和js中遍历数组和对象的总结
- C++ 与“类”有关的注意事项总结(十):类对象数组初始化(三种方法)