这几年,一直在前端开发,JavaScript虽然是很好的语言,但是在其中有些坑,你遇到了,就被坑了。
一、数组赋值(复制)引起的坑
var a = [1,2];
var b = a;
b[1] = 3;
console.log(a);
最后猜猜看,输出了是什么呢?
最后输出的是:[1,3]。
为什么呢?因为javascript分原始类型与引用类型(与java、c#类似)。Array是引用类型。b得到的是引用,所以对b的修改会影响到a。现在要分清楚了:
- 原始类型:number,string等,即是:var a = 1,b="2"等
- 引用类型:obejct等,即是:array,json等
解决方案:
1. 使用slice()
可使用slice()进行复制,因为slice()返回也是数组。
var array1 = new Array("1","2","3");
var array2;
array2 = array1.slice(0);
array1.length = 0;
alert(array2); //返回1、2、3
2. 使用concat()
注意concat()返回的并不是调用函数的Array,而是一个新的Array,所以可以利用这一点进行复制。
var array1 = new Array("1","2","3");
var array2;
array2 = array1.concat();
array1.length = 0;
alert(array2); //返回1、2、3
注意:这些只是指当数组中仅仅包含了原始类型,并没有包括其他引用类型的情况方可如此处理,如果包含其他情况,请看下面的处理方案。
二、数组深度克隆
参考链接:http://stackoverflow.com/questions/728360/most-elegant-way-to-clone-a-javascript-object
增加Array属性clone方法,添加判断,Object等对象的clone方法,代码如下:
Array.prototype.clone=function(){
var a=[];
for(var i=0,l=this.length;i<l;i++) {
if(this[i] instanceof Array){
a.push(this[i].clone());
}else if(this[i] instanceof Object){
a.push(clone(this[i]));
}else{
a.push(this[i]);
}
}
return a;
}
function clone(obj) {
// Handle the 3 simple types, and null or undefined
if (null == obj || "object" != typeof obj) return obj;
// Handle Date
if (obj instanceof Date) {
var copy = new Date();
copy.setTime(obj.getTime());
return copy;
}
if (obj instanceof Array) {
return obj.clone();
}
// Handle Object
if (obj instanceof Object) {
var copy = {};
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
}
return copy;
}
throw new Error("Unable to copy obj! Its type isn't supported.");
}