在这之前,我们回顾一下数据类型:数组,对象,字符,数字。(注:数组是特殊的对象)
其中,简单数据类型有:字符,数字;
var i = 1;
var j = "2";
var k = [1,2];
var l = {
theName : "obj"
}
console.log( typeof i); //number
console.log( typeof j); //string
console.log( typeof k); //object
console.log( typeof l); //object
当我们对 i 或 j 进行变量间的拷贝时的结果,与我们初学者想象中的结果是一致的
i = j;
i = 5;
console.log(i); // 5
console.log(j); // "2"
当我们对 k 和 l 进行拷贝,则需要注意了
var m = [];
m = k;
console.log(m); //[1, 2]
m[0] = "red";
console.log(k); //["red", 2]
我们声明了一个新的数组m,将k中的内容拷贝进来,打印,似乎没什么问题;
但是我们对m[0]进行改变的时候,此时打印了k,发现k的值也改变了,这是怎么一回事呢?
原来,当我们对复杂数据类型进行了变量之间的赋值时,并没有在内存中开辟一块新的空间,而是
直接让左边的变量指向了右边的地址 ,
所以,当左边进行改变时,右边也会同时改变。即我们对m进行赋值的时候,相当于对k进行了赋值
所以得出了以上代码的结果;(对象的结果也是如此,这里不再描述)。
简单来说:浅拷贝只是拷贝了表面一层,更深层次对象级别的只拷贝引用(地址)。
在我们ES6里面添加了一种浅拷贝的方法
Object.assign(target, sources);//target:目标,sources:来源
2.深拷贝
那我们该怎么样实现能赋值源数据的内容又不是单单地指向其地址呢?
这就是我们地深拷贝了——开辟一块新的内存,并将对象的每一层复制下来;
我们先创建一个新的对象;
var obj = {
id: 1,
name: 'andy',
msg: {
age: 18
},
color: ['pink', 'red']
};
var o = {};
封装一个函数deepCopy
//newobj为新对象,即我们要得到的拷贝 oldobj为源对象
function deepCopy(newobj, oldobj) {
}
首先,我们要得到对象中的数据,我们对其进行遍历
function deepCopy(newobj, oldobj) {
for (var k in oldobj) {
}
}
此时,对象中的数据有各种各样的类型,回顾前文,为了不让浅拷贝的现象出现我们不要直接对复杂的数据类型进行拷贝,应当让复杂的数据类型再次执行该函数(递归),一步一步地复制所有地简单数据类型到新的对象中。
function deepCopy(newobj, oldobj) {
for (var k in oldobj) {
// 判断我们的属性值属于那种数据类型
// 1. 获取属性值 oldobj[k]
var item = oldobj[k];
// 2. 判断这个值是否是数组
//不可讲判断数组和对象地顺序颠倒,因为数组也是特殊的对象
if (item instanceof Array) {
newobj[k] = [];
deepCopy(newobj[k], item)
} else if (item instanceof Object) {
// 3. 判断这个值是否是对象
newobj[k] = {};
deepCopy(newobj[k], item)
} else {
// 4. 属于简单数据类型
newobj[k] = item;
}
}
}
这样我们就完成了该函数,调用一下看看结果:
deepCopy(o, obj);
console.log(o);
console.log(obj);
o.msg.age = 20;
console.log(o);
console.log(obj);
注:此文章为本人学习该方面内容时为巩固记忆所写,若有不足之处还请指出。