前言:ECMAScript有五种简单数据类型(也称为基本数据类型),也有一种复杂数据类型,那就是object了。数组可以是数组对象,函数可以是函数对象,普通对象类型也是,这些object都存在对象引用的问题。
一、对象的引用
var arr = ['nick'];
var obj = {
name: 'nick',
hobit: ['eat']
}
var newArr = arr;
var newObj = obj;
newArr.push('freddy'); //给拷贝的数组插入队列('freddy')
newObj.name = 'freddy'; //修改拷贝的对象的name属性
console.log(arr); //输出原数组
console.log(obj); //输出原对象
console.log('-----分界线------');
arr = null; //将原数组的引用指针指向null
obj = null; //将原对象的引用指针指向null
console.log(newArr); //输出拷贝的数组
console.log(newObj); //输出拷贝的对象
运行结果:
会发现往newArr数组对象中push的“freddy”也出现在原有的arr中,然后我们将原有的arr数组对象指向null空对象指针,然后发现nreArr一样可以进行输出。其中发生了什么?
其实我们创建一个数组(对象)时,它单独开辟了一个新内存(空间),并不是属于任何人,
①如var arr = ['nick'];中,数组['nick']单独开辟了一个新内存(空间)。而var arr = ['nick'],只是把变量arr的指针指向了数组['nick'],并不是把['nick']赋值给arr。他们只存在引用的关系。
②我们让var newArr = arr;只是给变量newArr也添加了一个指向['nick']的指针。
③我们让arr = null; 是把变量arr的指针改变了,让他不再指向['nick'],而是指向null。
二、浅拷贝
var arr = ['nick'];
var obj = {
name: 'nick',
hobit: ['eat']
}
var copy = function(obj){
var newItem = null;
Array.isArray(obj) ? newItem = [] : newItem = {};
for(var key in obj){
newItem[key] = obj[key];
}
return newItem;
};
var newArr = copy(arr);
newArr.push('freddy'); //给拷贝后的数组插入队列('freddy')
console.log(arr); //输出被拷贝的数组
console.log(newArr); //输出拷贝的数组
var newObj = copy(obj);
newObj.name = 'freddy'; //修改拷贝对象的名字
newObj.hobit.push('sleep'); //给拷贝对象下的hobit数组插入队列('sleep')
console.log(obj); //输出被拷贝的对象
console.log(newObj); //输出拷贝的对象
运行结果:
通过浅拷贝,我们会发现修改拷贝的数组和对象,不会再影响原数组和原对象了。但是我们往拷贝对象的hobit数组中插入队列'sleep'时,会发现原有对象中的hobit也一样有了'sleep'了,这就是浅拷贝的弊端了。
三、深拷贝
var obj = {
name: 'nick',
hobit: ['eat']
};
var deepCopy = function(obj){
var newItem = null;
if(typeof obj !== 'object' || obj===null){
return obj; //如果传入obj不是object或者为null就退出递归,
}
Array.isArray(obj) ? newItem = [] : newItem = {};
for(var key in obj){
//arguments.callee 的作用是指向正在执行的函数的指针(也就是deepCopy函数本身)
newItem[key] = arguments.callee(obj[key]); //进行递归操作
}
return newItem;
};
var newObj = deepCopy(obj);
newObj.name = 'freddy';
newObj.hobit.push('sleep');
console.log(obj);
console.log(newObj);
输出结果:
这时,原对象跟拷贝对象之前就不会互相影响,即不存在引用关系了。