一、扩展Array原型,实现数组的深、浅拷贝
var arrayPrototype = {
clone:function(deep) {
if (deep === true) {
//如果是深度复制的话
var array = [];
this.forEach(function (object) {
if (object.constructor === Array ) {
if(object.clone){
array.push(object.clone(deep));
}else if(Array.clone){ //在Array上直接添加clone方法(三)时用到,此处可以注释掉
array.push(Array.clone(object,deep));
}
}else{
array.push(object);
}
});
return array;
} else {
return this.slice(0);
}
}
};
Array.attachExtendPrototype = function () {
for (var name in arrayPrototype) {
Array.prototype[name] = arrayPrototype[name];
}
};
Array.attachExtendPrototype();
大家不要疑惑,把clone方法添加到arrayPrototype是为了后期扩展代码的时候方便,如果你只需要扩展一个clone方法,那直接写Array.prototype.clone完全可以,但是如果我们想要在数组上扩展很多方法,比如清空数组、删除其中一个值等,那重复写起来就比较麻烦,所以我们采用这种策略模式去实现。
测试一下有没有实现拷贝功能吧
var b=[1,2,[3,3,3,[1,2,3]]]
var arr1 = ['a', b, 'c', 'd'];
var arr2 =arr.clone(true);//浅拷贝去掉true参数即可,自行测试
arr2[1][2][3][3]=4;
console.log(arr2[1]);
console.log(arr1[1]);
二、扩展Array原型出现的问题
但是将clone添加到原型上有一个问题,就是我们再用for in遍历数组的时候,会将继承来的方法一起遍历出来,
var arr=[1,2,3,4];
for(var i in arr){
console.log(arr[i]); //1,2,3,4,f(deep){...}
}
因为在原型上继承过来的方法是可枚举的,为了解决这种弊端,我们有一下几个方案:
1、在用for in遍历的时候,用hasOwnProperty过滤添加的扩展方法
var arr=[1,2,3,4];
for(var i in arr){
if(arr.hasOwnProperty(i)) //过滤继承过来的方法和属性
console.log(arr[i]); //1,2,3,4
}
2、直接使用for循环进行遍历
3、不要将扩展方法加到原型 (这一点在下面介绍)
三、将扩展方法直接加到Array上,避免for in循环时出现问题
首先解绑原型上的扩展
Array.detachExtendPrototype = function () {
for (var name in arrayPrototype) {
delete Array.prototype[name];
}
};
Array.detachExtendPrototype ()
解绑以后,我们开始继续在Array上绑定静态方法
Array.clone = function (array,deep) {
return arrayPrototype['clone'].call(array,deep);
};
这样,我们就解决的for in时出现的问题
测试深拷贝功能:
var b=[1,2,[3,3,3,[1,2,3]]]
var arr1 = ['a', b, 'c', 'd'];
var arr2 =Array.clone(arr1,true);
arr2[1][2][3][3]=4;
console.log(arr2);
console.log(arr1);