js的浅拷贝和深拷贝
最近解决的一个bug就是关于js的深浅拷贝的使用上,该bug就是在应该使用深拷贝的情况下使用浅拷贝,造成引用同一块堆内存对象,出错了!
所以自己有必要好好总结下,免得以后自已犯同样的错误。
浅拷贝:浅拷贝是拷贝引用,拷贝后的引用都是指向同一个对象的实例,彼此之间的操作会互相影响
深拷贝:在堆中重新分配内存,并且把源对象所有属性都进行新建拷贝,以保证深拷贝的对象的引用图不包含任何原有对象或对象图上的任何对象,
拷贝后的对象与原来的对象是完全隔离,互不影响
举个栗子吧!看下面一段代码
var a = {name:'张三',age:24} console.log(a.name)//张三 console.log(a.age)//24 var b = a; //浅拷贝,拷贝引用,a,b都指向同一块堆内存。 b.name = '李四'; b.age = 34; console.log(a.name)//李四 console.log(a.age)//34 console.log(b.name)//李四 console.log(b.age)//34
再看下面一段代码,在原有的基础上修改的:
var a = {name:'张三',age:24} console.log(a.name)//张三 console.log(a.age)//24 var b = {}; //这是深拷贝,a,b不指向同一内存哦! b.name = a.name; b.age = a.age; b.name = '李四';//修改b.name属性的值 b.age = 34;//修改b.age属性的值 console.log(a.name)//'张三' console.log(a.age)//24 console.log(b.name)//李四 console.log(b.age)//34
其实说白了,就是js中对象实例是保存在堆内存中,而不是栈内存中,对象名中保存的是对象实例在堆内存中的地址!所以才出现深浅拷贝的问题。
最后贴出一段代码,实现一个函数clone,可以对JavaScript中的5种主要的数据类型(包括Number、String、Object、Array、Boolean)进行值复制。
/**
* 对象克隆
* 支持基本数据类型及对象
* 递归方法
*/
function clone(obj) { var o; switch (typeof obj) { case "undefined": break; case "string": o = obj + ""; break; case "number": o = obj - 0; break; case "boolean": o = obj; break; case "object": // object 分为两种情况 对象(Object)或数组(Array) if (obj === null) { o = null; } else { if (Object.prototype.toString.call(obj).slice(8, -1) === "Array") { o = []; for (var i = 0; i < obj.length; i++) { o.push(clone(obj[i])); } } else { o = {}; for (var k in obj) { o[k] = clone(obj[k]); } } } break; default: o = obj; break; } return o; }