题目描述:
实现一个可以对JavaScript中五种主要数据类型(Boolean、Number、String、Object、Array)进行值复制的函数
1、数组复制
1.1 浅复制
var arr = ['one','two','three'];
var arrCopy = arr;
arrCopy[0] = 'test';
console.log(arr); //test,two,three
console.log(arrCopy); //test,two,three
问题:如果只是简单的将它赋予其它变量,那么我们改变其中任何一个,然后其他的也会跟着改变,这就导致了问题的发生。
1.2 深复制
- 方法一:js的slice函数
arrCopy = arr.slice(0);
- 方法二:js的concat方法
arrCopy = arr.concat();
2对象的深浅拷贝
2.1 浅拷贝
var a = {a:'aaa',b:'bbb'};
var b = a;
这种直接进行赋值操作的就是浅拷贝,会出现和数组一样的问题,改变一个的属性,其他的也会改变。
2.2 深拷贝
- 方法一:使用JSON.parse()方法
/* ================ 深拷贝 ================ */
function deepClone(initalObj) {
var obj = {};
try {
obj = JSON.parse(JSON.stringify(initalObj));
}
return obj;
}
/* ================ 客户端调用 ================ */
var obj = {
a: {
a: "world",
b: 21
}
}
var cloneObj = deepClone(obj);
cloneObj.a.a = "changed";
console.log(obj.a.a); // "world"
这种方法简单易用。
但是这种方法也有不少坏处,譬如它会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。
这种方法能正确处理的对象只有 Number, String, Boolean, Array, 扁平对象,即那些能够被 json 直接表示的数据结构。RegExp对象是无法通过这种方式深拷贝。
2. 方法二:递归拷贝
var deepCopy = function(source) {
var result = {};
for(var key in source) {
result[key] = typeof source[key] === 'object'?arguments.callee(source[key]):source[key];
}
return result;
}
var a = {a:'aaa',b:'bbb'};
var b = deepCopy(a);
这样,拷贝的值和原来的值就不会相互影响了。
五种值的复制的实现
function copy(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(Array.isArray(obj)) {
o = [];
for(var i = 0,length = obj.length;i<length;i++) {
o.push(arguments.callee(obj[i]));
}
}else {
o = {};
for(var k in obj) {
o[k] = arguments.callee(obj[k]);
}
}
break;
default:
o = obj;
break;
}
return o;
}