十四、浅拷贝
1,什么是浅拷贝?
浅拷贝(浅克隆)指的是只拷贝第一层的原始类型值,和第一层的引用类型地址。对象的 Object.assign(),数组的 Array.prototype.slice() 和 Array.prototype.concat(),还有 ES6 的扩展运算符,都属于浅拷贝。
2,clone 方法
(1)clone 方法可以创建一个 value 的浅拷贝。 下面是浅拷贝一个 Object 样例,可以发现浅拷贝确实只拷贝了第一层的原始类型值,和第一层的引用类型地址。var object = { 'a': 1, 'b': { 'c':2, 'd':3 } }; var shallow = _.clone(object); object.a = 1111; object.b.c = 2222; console.log(object); console.log(shallow);
(2)下面是浅拷贝一个数组样例,同样可以发现浅拷贝确实只拷贝了第一层的原始类型值,和第一层的引用类型地址。
var objects = [{ 'a': 1 }, { 'b': 2 }, { 'c': 3 }]; var shallows = _.clone(objects); objects.pop(); //移除最后一个元素 objects[0].a = 11111; // 修改第一个元素值 console.log(objects); console.log(shallows);
3,cloneWith 方法
(1)cloneWith 方法类似 clone,它还可以接受一个 customizer 定制返回的克隆值。 如果 customizer 返回 undefined 将会使用拷贝方法代替处理。
_.cloneWith(value, [customizer])
(2)下面使用 cloneWith 方法浅拷贝一个 DOM 对象:
cloneNode() 方法介绍:
- cloneNode() 方法可创建指定的节点的精确拷贝。
- cloneNode(false) 表示只复制当前节点。
function customizer(value) { if (_.isElement(value)) { return value.cloneNode(false); } } var el = _.cloneWith(document.body, customizer); console.log(el === document.body); // => false console.log(el.nodeName); // => 'BODY' console.log(el.childNodes.length); // => 0
十三、深拷贝
1,什么是深拷贝?
深拷贝(深克隆)指拷贝所有的属性值,以及属性地址指向的值的内存空间。最简单的深拷贝方法就是利用 JSON 实现:JSON.parse(JSON.stringify(obj))。但这种方法有两个问题:
- 这种方式只能深拷贝对象和数组,对于其他种类的对象,会失真。
- 同时由于 JSON 内部用了递归的方式。数据一但过多,就会有递归爆栈的风险。
2,cloneDeep 方法
(1)cloneDeep 方法可以创建一个 value 的深拷贝。 下面是深拷贝一个 Object 样例,可以发现拷贝后的值与拷贝前的值是完全独立,互不影响的。
var object = { 'a': 1, 'b': { 'c':2, 'd':3 } }; var shallow = _.cloneDeep(object); object.a = 1111; object.b.c = 2222; console.log(object); console.log(shallow);
(2)下面是深拷贝一个数组样例,同样可以发现拷贝后的值与拷贝前的值是完全独立,互不影响的。
3,cloneDeepWith 方法
(1)cloneDeepWith 方法类似 cloneDeep,它还可以接受一个 customizer 定制返回的克隆值。 如果 customizer 返回 undefined 将会使用拷贝方法代替处理。
_.cloneDeepWith(value, [customizer])
(2)下面使用 cloneDeepWith 方法深拷贝一个 DOM 对象:
cloneNode() 方法介绍:
- cloneNode() 方法可创建指定的节点的精确拷贝。
- cloneNode(true) 表示除了复制当前节点外,还将递归复制当前节点的所有子孙节点。
function customizer(value) { if (_.isElement(value)) { return value.cloneNode(true); } } var el = _.cloneDeepWith(document.body, customizer); console.log(el === document.body); // => false console.log(el.nodeName); // => 'BODY' console.log(el.childNodes.length); // => 20