js 中的深拷贝和浅拷贝

 Shallow copy && Deep copy

 
对于字符串类型,浅复制是对值的复制,对于对象来说,浅复制是对对象地址的复制,并没 有开辟新的栈,也就是复制的结果是两个对象指向同一个地址,修改其中一个对象的属性,则另一个对象的属性也会改变,
举个栗子
var arr = [1,2,3];
var arrCopy = arr;
arrCopy[0] = 100;   // 修改新数组的第0个值;
arr[0]===arrCopy[0];  //true  原来的数组四不四也变了 
 而很多数情况下我们需要的是 新得到的对象与原来的对象互不相干,于是乎:

 深复制则是开辟新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。我们来看看以下方法。

Array 的 slice 和 concat 方法

//slice
var a = [1,2,3];
var b = a.slice(); 
b === a; // false

//concat
var a = [1,2,3];
var b = a.concat(); 
b === a;  // false

你可能会说你看他们没有指向同一个地址啊,喵的肯定是 deep copy,表捉急。请看下面:

var a = [[1,2,3],4,5];
var b = a.slice();
a[0][0]===b[0][0]; // true 

true 了我去,第二层的复制明显不是 deep copy 啊。

jQuery ——  $.extend()

我们可以通过 $.extend() 方法来完成  深浅复制。这个方法可以传入一个参数:deep(true or false),表示是否执行深复制(如果是深复制则会执行递归复制)。

var x = {
    a: 1,
    b: 2,
    c: {f:{g:1}}
};

var y = $.extend({}, x),          //浅 copy
    z = $.extend(true, {}, x);    //深 copy

y.c.f === x.c.f       // true
z.c.f === x.c.f       // false    $.extend 的用法很有意思,不单单只是 深浅copy, 有兴趣的崽儿可以到这个同学这里看看,总结的挺好 https://segmentfault.com/a/1190000004082170

借助 JSON 全局对象

针对纯 JSON 数据对象的深复制,使用 JSON 全局对象的 parse 和 stringify 方法来实现深复制也算是一个简单讨巧的方法。

JOSN 对象中的 stringify 可以把一个 js 对象序列化为一个 JSON 字符串,parse 可以把 JSON 字符串反序列化为一个 js 对象,这两个方法实现的是深拷贝。然而使用这种方法会有一些隐藏的坑,

它能正确处理的对象只有 Number, String, Boolean, Array, 扁平对象(function 就歇菜了,原型链也没了),即那些能够被 json 直接表示的数据结构。


var arr = [0,1,2];
var arrCopy =  JSON.parse(JSON.stringify(arr));
arrCopy[0] = 333;
arr[0]===arrCopy[0];  // false
did u see that, 互不干扰,和谐盛世。

总结下:

Array 的 slice 和 concat 方法 和 jQuery 中的 extend 复制方法,他们都会复制第一层的值,对于 第一层 的值都是 深拷贝,

而到 第二层 的时候 Array 的 slice 和 concat 方法就是 复制引用 ,jQuery 中的 extend 复制方法 则 取决于 你的 第一个参数, 也就是是否进行递归复制。

而  JSON.parse(JSON.stringify(arr)) 在排除 被复制对象的 function 和原型链 之外,就是完全的复制啦 。

今天,就酱紫。88了。

原文地址:https://www.cnblogs.com/guoyu234/p/7383232.html