克隆就是创建副本,副本具有与原数组相同的值。 Array 类中没有克隆数组的方法,但用户可以使用变通的方法来实现克隆。
通过调用 concat()或 slice()方法,可以创建数组的浅表副本。在浅表副本中,如果原始数组的元素是复杂数据类型,则元素值指向对象的引用而非对象本身,与原始数组一样,浅表副本的元素值也指向对象的引用,对对象所做的任何更改都会在两个数组中反映出来。例如下面的代码,演示了如何实现浅表克隆:
var person = new Object(); //
创建一个复杂数据类型作为数组元素 person.sex = 'male';
person.age = 28;
var oArray = ['tom', person];
var newArray = oArray.concat(); // 克隆
console.log(oArray[1].age); // 返回28
console.log(newArray[1].age); // 返回28
// 现在改变指向的对象,那么将同时影响两个数组
person.age = 29;
console.log(oArray[1].age); // 返回29
console.log(newArray[1].age); // 返回29 // 也可以这样改变指向的对象
oArray[1].age = 30;
console.log(newArray[1].age); // 返回30
console.log(person.age); // 返回30
深度克隆是相对于浅表克隆而言的,在克隆的深度副本中,不断复制索引,还将复制原始数组中的所有对象,从而使新数组和原始数组指向不同的对象。
在 JavaScript 中,实现深度克隆的方法是:将原始数组中的引用类型数据读出来然后重新填充新数组。
下面来创建一个实用函数,该函数根据参数 deep 的值确定是将参数_array 定义的数组克隆为浅表副本还是深度副本,实现如下:
/***
* @param _array 被克隆的数组
* @param deep 定义是否深度克隆
* @return Array 返回克隆的数组
* @throws Error 参数数量不正确
*/
function cloneArray(_array, deep) {
if (arguments.length == 1) {
var isDeep = false;
} else if (arguments.length == 2) {
var isDeep = deep;
} else {
throw new Error('参数数量不正确');
return;
}
var newArray = _array instanceof Array ? [] : {};
if (isDeep) {
for (var i in _array) {
var prop = _array[i];
if (typeof prop == 'object') {
if (prop instanceof Array) {
newArray[i] = [];
for (var j = 0; j < prop.length; j++) {
if (typeof prop[j] != 'object') {
newArray[i].push(prop[j]);
} else {
newArray[i].push(cloneArray(prop[j]), true);
}
}
} else {
newArray[i] = cloneArray(prop, true);
}
} else {
newArray[i] = prop;
}
}
} else {
newArray = _array.concat();
}
return newArray;
}
该函数有以下3种使用方法:
var newArray = cloneArray(oArray); // 浅表克隆
var newArray = cloneArray(oArray, false); // 浅表克隆
var newArray = cloneArray(oArray, true); // 深度克隆
下面验证一下该函数:
var person = new Object(); // 创建一个复杂数据类型作为数组元素
person.sex = 'male';
person.age = 28;
var oArray = ['tom', person];
// ===== 克隆
cloneArray(oArray, true); // =====
console.log(oArray[1].age); // 返回28
/console.log(newArray[1].age); / / 返回28;
// 现在改变指向的对象,那么仅影响原始数组,而不影响克隆的数组
person.age = 29;
console.log(oArray[1].age); // 返回29
console.log(newArray[1].age); // 返回28