在 JS 中有一些基本类型像是Number
、String
、Boolean,
而对象就是像这样的东西{ name: 'Larry', skill: 'Node.js' },对象跟基本类型最大的不同就在于他们的传值方式。
var a = 25;
var b = a;
b = 18;
console.log(a);//25
console.log(b);//18
基本类型是按值传递,就像上面那样,修b的值并不会改到a
但对象就不同,对象传的是按引用传值。比如:
var obj1 = { a: 10, b: 20, c: 30 };
var obj2 = obj1;
obj2.b = 100;
console.log(obj1);
// { a: 10, b: 100, c: 30 } <-- b 被改到了
console.log(obj2);
// { a: 10, b: 100, c: 30 }
关系图如下 :
因为引用都指向同一个地址,所以修改obj2的,obj的值也被修改了。这就是浅拷贝。
要避免这样的错误发生就要写成这样:
var obj1 = { a: 10, b: 20, c: 30 };
var obj2 = { a: obj1.a, b: obj1.b, c: obj1.c };
obj2.b = 100;
console.log(obj1);
// { a: 10, b: 20, c: 30 } <-- b 沒被改到
console.log(obj2);
// { a: 10, b: 100, c: 30 }
这样就是深拷贝,不会改到原本的obj1。但是这样一个个赋值,对象不复杂的情况下还是可以使用的。若对象很复杂,不推荐这样写。
深拷贝的实现算法
步骤1
var person = {
sex : '女',
other : {
height : '175cm',
}
}
function deepCopy(obj){
return obj;
}
var obj = deepCopy(person);
obj.sex = '男';
console.log(person);
console.log(obj);
把person传进去deepCopy函数,该函数会返回一个对象给obj。(当然,上面的代码还未实现)
步骤2
var person = {
sex : '女',
other : {
height : '175cm',
}
}
function deepCopy(obj){
let copyObj = {};
for(let i in obj){
copyObj[i] = obj[i];
}
return copyObj;
}
var obj = deepCopy(person);
obj.sex = '男';
console.log(person);
console.log(obj);
打印结果 :
结果貌似可以。但是只是sex是深拷贝,other还是浅拷贝。如 :
var person = {
sex : '女',
other : {
height : '175cm',
}
}
function deepCopy(obj){
let copyObj = {};
for(let i in obj){
copyObj[i] = obj[i];
}
return copyObj;
}
var obj = deepCopy(person);
obj.sex = '男';
obj.other.height = '200cm'; //改成200cm
console.log(person);
console.log(obj);
打印结果 :
所以我们需要判断下,传入的对象是否还有子对象,如果有子对象,则在调用deepCopy函数(递归实现)
var person = {
sex : '女',
other : {
height : '175cm',
hobby : {
playGame : '麻将,吃鸡,王者',
skill : {
1 : 'ps',
2 : 'php'
}
}
}
}
function deepCopy(obj,obj2)
{
let copyObj = obj2 || {};
for(let key in obj)
{
let value = obj[key];
//如果对象还包含子对象,则在调用一次自己
if(typeof value === 'object')
{
copyObj[key] = {};
arguments.callee(value,copyObj[key]);
}
//对象只是普通的值
else
{
copyObj[key] = obj[key];
}
}
return copyObj;
}
var obj = deepCopy(person);
//修改obj的值
obj.other.height = '200CM';
obj.other.hobby.playGame = 'none';
obj.other.hobby.skill['2'] = 'node';
//打印
console.log(person);
console.log(obj);
打印结果 :