引子:表单数据的克隆
工作中我们需要用到对象或者数组的复制功能
- 提交的form表单,需要进行处理,例如将表单中的数组变成','连接的字符串,这个时候我们直接对原表单直接处理是不妥当的
那么问题来了,我该用什么方法去克隆这个含有数组的表单呢?
深克隆和浅克隆的区别
在解决上述问题之前,我们应该明确一点什么是深克隆,什么是浅克隆?
浅克隆是把一个对象里面的数据复制一份出来,当对象中含有对象或者数组这种引用类型的数据时,浅克隆也只是复制其引用地址,因此修改新复制的对象中引用类型的数据时,原对象也是会改变的,因此浅克隆适用于对象或数组中只有简单数据类型时使用
对于上面的表单数据的克隆来说,此时我们应该采用的是深克隆的方式,因为我们并不想让原表单对象随我们新复制出对象的改变而改变
Array&Object通用深克隆方法
着急的兄弟姐妹可以不用看下面,直接copy下面的通用方法,想多了解的,欢迎继续看下去
一、最简单粗暴的方法,缺点是不能复制函数
let new = JSON.parse(JSON.stringify(target))
二、通过递归方式的方法,解决了不能复制函数的问题(最全面的深克隆方法)
function deepClone(obj) {
var o, i, j, k;
if (typeof (obj) != "object" || obj === null) return obj;
if (obj instanceof(Array)) {
o = [];
i = 0;
j = obj.length;
for (; i < j; i++) {
if (typeof (obj[i]) == "object" && obj[i] != null) {
o[i] = arguments.callee(obj[i]);
} else {
o[i] = obj[i];
}
}
} else {
o = {};
for (i in obj) {
if (typeof (obj[i]) == "object" && obj[i] != null) {
o[i] = arguments.callee(obj[i]);
} else {
o[i] = obj[i];
}
}
}
return o;
}
Object克隆
一、浅克隆
- Object.assign({}, targetObj) 查看Object.assgin的介绍
let targetObj = { a: [1, 2], b: 2 } let obj = Object.assign({}, targetObj) targetObj.a[0] = 0 console.log(obj)
- 遍历目标对象的属性,赋给新的对象
通过上面的代码可知,此方法也是浅克隆let targetObj = { a: [1, 2], b: 2 } let obj = {} for (var k in targetObj) { obj[k] = targetObj[k] } targetObj.a[0] = 0 console.log(obj)
- es6的扩展运算符...
let targetObj = { a: [1, 2], b: 2, c: function () { consle.log(333) } } let obj = {...targetObj} targetObj.a[0] = 0 console.log(obj, targetObj)
二、深克隆
-
JSON.parse
把对象序列化再解析回来,对象中有函数function则不能正确复制
let targetObj = { a: [1, 2], b: 2, c: function () { consle.log(333) } } let obj = {} obj = JSON.parse(JSON.stringify(targetObj)) targetObj.a[0] = 0 console.log(obj)
通过上面代码结果可知,目标对象的改变不会影响到新对象的值,然而属性c并没有复制过来
Array克隆
一、浅克隆
- 数组遍历赋值
let targetArr = [1, {a: 1, b:2}, 3] let arr = [] for (var i = 0, len = targetArr.length; i < len; i++) { arr[i] = targetArr[i] } targetArr[1].a = 0 console.log(arr, targetArr)
- concat
let targetArr = [1, {a: 1, b:2}, 3] let arr = targetArr.concat() targetArr[1].a = 0 console.log(arr, targetArr)
- es6扩展运算符...
let targetArr = [1, {a: 1, b:2}, 3] let arr = [...targetArr] targetArr[1].a = 0 console.log(arr, targetArr)
- slice
let targetArr = [1, {a: 1, b:2}, 3] let arr = targetArr.slice() targetArr[1].a = 0 console.log(arr, targetArr)
- Object.assign()
let targetArr = [1, {a: 1, b:2}, 3] let arr = Object.assign([], targetArr) targetArr[1].a = 0 console.log(arr, targetArr)
二、深克隆
- JSON.parse() 方法与对象一样,也是不能复制函数,区别在于新数组中函数所在位置是个null,对象中则不进行任何处理
let targetArr = [1, {a: 1, b:2}, 3, function(){console.log(111)}] let arr = JSON.parse(JSON.stringify(targetArr)) targetArr[1].a = 0 console.log(arr, targetArr)