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了。