js中对象、数组的深拷贝

通常我们对数组、对象、对象数组进行简单赋值运算只是创建了一份原内容的引用,指向的仍然是同一块内存区域,修改时会对应修改原内容,而有时候我们并不需要这种模式,这就需要对内容进行深拷贝。

一、数组的深拷贝

方法1:遍历复制

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;
}

方法2:slice()

该方法并不会修改数组,而是返回一个子数组。

var arr = ["a", "b"];
arrCopy = arr.slice(0);
arrCopy[1] = "c";
arr   // => ["a", "b"] 
arrCopy   // => ["a", "c"]

方法3:contat()

该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。

var arr = ["a", "b"];
arrCopy = arr.concat();
arrCopy[1] = "c";
arr   // => ["a", "b"] 
arrCopy   // => ["a", "c"]

二、对象的深拷贝

方法1:

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 }

方法2:简单粗暴,JSON.parse(JSON.stringify(obj));

JSON.stringify()  

1)object参数:是要转为字符串的JSON对象。
 2)replacer参数:可选,这个参数是一个过滤器,可以是改变字符串转换过程的函数,也可以是一组String和Number对 象。 这些对象用作一个白名单,用于选择要转换为字符串的对象的属性。如果这个值是空或没有提供,则在所得的JSON字符串中包含对象的所有属性。

如果过滤器参数是一个数组,那么JSON.stringify()的结果中将只包含数组中列出的属性。数组元素与将要序列化的对象中的属性是对应的,因此在返回的结果字符串中,就只会包含这两个属性。

如果第二个参数是函数,那么结果就会稍有不同。传入的函数接收两个参数,属性名和属性值。根据属性名就可以知道应该如何处理要序列化的对象中的属性。属性名只能是字符串,而在值并非键值对结构的值时,键名可以是空字符串。

 3)space参数:可选,是一个String或Number对象,用于把空白插入输出的JSON字符串,以提高可读性。如果这是一个数值,则表示用作空白的空格字符数;如果该数值大于10,就取其值为10;小于1的值表示不应使用空格。如果这是一个字符串(如果该字符串多于10个字符,就取前10个字符),就把该字符串用作空白。如果没有提供这个参数(或者为空),就不使用空白。

JSON.parse()

 参数
       1)text:必需。 一个有效的 JSON 字符串。
       2)reviver:可选。 一个转换结果的函数,这个函数被称为还原函数,这个函数接收两个参数,一个键和一个值。 将为对象的每个成员调用此函数。 如果成员包含嵌套对象,则先于父对象转换嵌套对象。 对于每个成员,会发生以下情况:


如果 reviver 返回一个有效值,则成员值将替换为转换后的值。
如果 reviver 返回它接收的相同值,则不修改成员值。
如果 reviver 返回undefined,则删除成员。(我在FF和chrome下试验的是返回undefined后,会删除成员,返回null,只会赋值为null)
 

三、对象数组的深拷贝

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 }]]

猜你喜欢

转载自blog.csdn.net/qq_35504206/article/details/83303157