前言:ECMAScript有五种简单数据类型(也称为基本数据类型),也有一种复杂数据类型,那就是object了。数组可以是数组对象,函数可以是函数对象,普通对象类型也是,这些object都存在对象引用的问题。
一、对象的引用
var arr = ['nick','freddy','mike']; var newArr = arr; newArr.push('james'); console.log(arr); //输出原有的arr arr = null; //把原有的arr指向null空对象指针 console.log(newArr); //输出newArr
输出结果:
会发现往newArr数组对象中push的“james”也出现在原有的arr中,然后我们将原有的arr数组对象指向null空对象指针,然后发现nreArr一样可以进行输出。其中发生了什么。
其实我们创建一个数组(对象)时,它单独开辟了一个新内存(空间),并不是属于任何人,
①如var arr = ['nick','freddy','mike'];中,只是把arr指向了数组['nick','freddy','mike'],并不是把['nick','freddy','mike']赋值给arr,
②我们让var newArr = arr;只是给newArr添加了一个指向['nick','freddy','mike']的指针。
③我们让arr = null; 是把arr的指针改变了,让他不再指向['nick','freddy','mike'],而是指向null
二、浅拷贝
①浅拷贝数组
var arr = ['nick','freddy','mike']; function copy(arr){ var newArr = []; for(var i in arr){ newArr[i] = arr[i]; } return newArr; } var arr2 = copy(arr); arr2.push('james'); console.log(arr2); console.log(arr);
输出结果:
通过创建新的数组(开辟新的数组空间),然后用for in循环,给他传入arr中所有的值。
②浅拷贝对象
var userMsg = { nick: { name: 'nick', age: 18, sex: '男' }, freddy: { name: 'freddy', age: 24, sex: '男' } }; function copy(obj){ var newObj = {}; for(var i in obj){ newObj[i] = obj[i]; } return newObj; } var userMsg2 = copy(userMsg); userMsg2.mike = { //userMsg2下新添加一个mike对象 name: 'mike', age: 24, sex: '男' }; console.log(userMsg2); console.log(userMsg); userMsg2.nick.sex = '女'; console.log(userMsg2.nick.sex); console.log(userMsg.nick.sex);
输出结果:
①浅拷贝后,给userMsg2下新添了一个mike对象,然后分别输出userMsg2跟userMsg,然后发现浅拷贝发挥了功效,userMsg2新添的mike对象不会影响userMsg。
②但是当我们修改userMsg2下的nick对象的sex值,然后分别输出userMsg2,userMsg下nick对象的sex值,发现两个的sex的值都被修改了。这就是浅拷贝的不足之处了,userMsg下的nick,freddy对象的虽然被拷贝过去了,当是他们的对象引用仍然存在。
三、深拷贝
var userMsg = { nick: { name: 'nick', age: 18, sex: '男' }, freddy: { name: 'freddy', age: 24, sex: '男' } }; function deepCopy(obj){ if(typeof obj != 'object'|| obj==null){ return obj; //如果传入obj不是object或者为null就退出递归, } var newObj = {}; for(var i in obj){ //arguments.callee 的作用是指向正在执行的函数的指针(也就是deepCopy函数本身) newObj[i] = arguments.callee(obj[i]); //进行递归操作 } return newObj; } var userMsg2 = deepCopy(userMsg); userMsg2.mike = { //userMsg2下新添加一个mike对象 name: 'mike', age: 24, sex: '男' }; console.log(userMsg2); console.log(userMsg); userMsg2.nick.sex = '女'; console.log(userMsg2.nick.sex); console.log(userMsg.nick.sex);
输出结果:
这时,就把userMsg下的nick,freddy对象的也拷贝了一次,分别跟它们创建了新的"空间"。这时就不存在对象引用带来的影响。