浅拷贝:就是简单的值的传递。jquery
深拷贝:达到了真正意义上的拷贝,很好的解决了引用类型的拷贝问题,采用递归的方法去复制拷贝对象,从而解决浅拷贝的弊端。数据结构
在JS中,基本类型(Number,String,Boolean等)和 对象(Array,Object等)最大的不一样在于它们的传值方式。基本类型是按值传递,对象按引用传值。函数
var a = 1 var b = 2 b = 3 console.log(a) //1 console.log(b) //3 //修改了b不会影响到a的值 var oa = {a:1,b:2,c:3} var ob = oa; ob.a = 4 console.log(oa) //{a:4,b:2,c:3} 被修改了 console.log(ob) //{a:4,b:2,c:3} //修改了ob中属性的值,也会把oa中相同属性的值一块儿修改,由于它们根本就是同一个对象,这就是所谓的浅拷贝 var o1 = {a:1,b:2,c:3} var o2 = {a:o1.a,b:o1.b,c:o1.c} o2.a = 4 console.log(o1) //{a:1,b:2,c:3} 没有被修改 console.log(o2) //{a:4,b:2,c:3} //这就是基本的深拷贝
浅拷贝只复制指向某个对象的指针,而不复制对象自己,新旧对象仍是共享同一块内存。但深拷贝会另外创造一个如出一辙的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。ui
一、简单的复制语句spa
function copy(source){ var target = {} for(var i in source){ target [i] = source[i] } return target; } var o = { a:1, b:{ x:1,y:'hello'}, c:[1,2,3], d:function(){ console.log('hello') } } var clone = copy(o); console.log(clone) //输出clone对象 clone.b.x = 2; clone.c = [4,5,6] clone.d = function(){console.log('world')} console.log(o) //输出o对象,o对象也被修改
二、Object.assign()指针
该方法能够把任意多个的源对象自身的可枚举属性拷贝给目标对象,返回目标对象。code
var source = { a:{ b:'hello', c:23 } } var copy = Object.assign({},source ) copy.a.b = 'world' console.log(source.a.b) // world source对象被修改
注意:该方法能够处理一层的深度拷贝,以下:对象
var source = {a:1,b:2,c:3} var target = Object.assign({},source) target.b = 100; console.log(source) //{a:1,b:2,c:3} console.log(target) //{a:1,b:100,c:3}
var a = [1,{a:2},3] var b = a.slice(1,2) console.log(a) // [1,{a:2},3] console.log(b) // [{a:2}] b[0].a = 100; console.log(a) // [1,{a:100},3] 被修改了 console.log(b) // [{a:100}]
var a = [1,{a:2},3] var b = a.concat(4,5) console.log(a) // [1,{a:2},3] console.log(b) // [1,{a:2},3,4,5] b[1].a = 100; console.log(a) // [1,{a:100},3] 被修改了 console.log(b) // [1,{a:100},3,4,5]
一、手动复制blog
即把一个对象的属性 复制 到另外一个对象的属性上。递归
要一个一个复制,很麻烦。而且这也不能算是真正的深拷贝,由于对象里面并未包含复杂类型(对象)
var o1 = {a:1,b:2,c:3} var o2 = {a:o1.a,b:o1.b,c:o1.c} o2.a = 4 console.log(o1) //{a:1,b:2,c:3} 没有被修改 console.log(o2) //{a:4,b:2,c:3}
var source = { a: { b:1 } } var copy = { a: source.a } copy.a.b = 2 console.log(source.a.b) // 2 被修改了 console.log(source === copy) //false console.log(source.a === copy.a) //true
二、Object.assign()方法,对象只有一层深度时可使用
三、转成JSON再转回来
用JSON.stringify
把对象转成字符串,再用JSON.parse
把字符串转成新的对象。
var source = { a: { b:1} } var copy = JSON.parse(JSON.stringify(source)) copy.a.b = 2; console.log(source.a.b) //1 未被修改 console.log(source === copy) //false console.log(source.a === copy.a) //false
该方法缺点:
var source = {func:function(){}} var copy = JSON.parse(JSON.stringify(source)) console.log(typeof source.func) //function console.log(typeof copy.func) //undefined
四、递归拷贝
function deepCopy(target,source){ var o = target || {} for(var i in source){ if(typeof source[i] === 'object'){ o[i] = (source[i].constructor === Array) ? [] : {} arguments.callee(o[i],source[i]) }else{ o[i] = source[i] } } return o; } var target= {} var source = {a: { b:'hello',c:23 }} deepCopy(target,source)
五、Object.create()
function deepCopy(target,source){ var o = target || {} for(var i in source){ if(typeof source[i] === 'object'){ o[i] = (source[i].constructor === Array) ? [] : Object.create(source[i])
arguments.callee(o[i],source[i]) }else{ o[i] = source[i] } } return o; } var target= {} var source = {a: { b:'hello',c:23 }} deepCopy(target,source)
六、jQuery 的 $.extend()
var $ = require('jquery'); var source = { a: 1, b: {x: { y: 1 } }, c: [1, 2, 3] }; var copy= $.extend(true, {}, source); console.log(source.b.x === copy.b.x);// false
七、lodash 的 _.cloneDeep()
var _ = require('lodash'); var source= { a: 1, b: { x: { y: 1 } }, c: [1, 2, 3] }; var copy = _.cloneDeep(source); console.log(source.b.x=== copy.b.x);// false