当咱们利用v-bind:来绑定属性向子组件传递对象的时候,有时候咱们须要子组件改变的时候不改变父组件的值,通常能够利用JSON.stringify(JSON.parse(jsonstr))将传递来的对象赋值到子组件本身的data,这样作的原理是对传过来的值从新赋予一个空间,从而解决双向绑定。,可是es6有一个深度赋值的方法也能够解决这个问题, let obj= Object.assign({}, obj)也能够解决。es6
好比一个数组(array)浅度拷贝是当数组a变量成数组b的时候,b改变里面的数组数值的时候,a也随着改变.json
深度拷贝是当当数组a变量成数组b的时候,b改变里面的数组数值的时候,a里面的数组数组不随着改变,数组
var arr = ["a", "b", "c", "d", "e"];
var Arr = JSON.stringify(arr); //先转化为string字符串的类型
var Brr = JSON.parse(Arr); //在解析字符串的类型
Brr[1] = 'h'; //这样修改Brr中的数组的时候就不会影响到arr里面数组的值
console.log('arr:' + arr); //结果是arr:a,b,c,d,e
console.log("Arr:" + Brr); //结果是Arr:a,b,c,d,e
复制代码
那么为何浅度拷贝会改变a的数组值而深度拷贝则不会呢?函数
由于浅度拷贝指向的是同一个内存,而深度拷贝是增长了一个新的内存,因此不会影响到原来a的内存, 所 以就不会改变原来的值 eg.
测试
var arr = ["a", "b", "c", "d", "e"];
var Arr = arr;
Arr[1] = 'h';
console.log('arr:' + arr); //arr的下标1的‘b’也变成了‘h’ 结果是:arr:a,h,c,d,e
console.log("Arr:" + Arr); //结果是:Arr:a,h,c,d,e
复制代码
对于数组的深拷贝常规的有三种方法:ui
方法一:遍历复制spa
var arr = ["a", "b"], arrCopy = [];
for (var item in arr) arrCopy[item] = arr[item];
arrCopy[1] = "c";
arr // => ["a", "b"]
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自己的函数咱们能够更加便捷地实现这个操做。code
方法二: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"]
复制代码
对于数组的深拷贝咱们有了概念,那么通常对象呢?
咱们给出一个对象:
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 = [{ "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 }]]
复制代码