js 深拷贝和浅拷贝
参考链接
https://www.jianshu.com/p/cf1e9d7e94fb
一、JS的基本数据类型
-
基本数据类型:String,Boolean,Number,Undefined,Null;
-
引用数据类型:Object(Array,Date,RegExp,Function);
-
基本数据类型和引用数据类型的区别:
1、保存位置不同:基本数据类型保存在栈内存中,引用数据类型保存在堆内存中,然后在栈内存中保存了一个对堆内存中实际对象的引用,即数据在堆内存中的地址,JS对引用数据类型的操作都是操作对象的引用而不是实际的对象,如果obj1拷贝了obj2,那么这两个引用数据类型就指向了同一个堆内存对象,具体操作是obj1将栈内存的引用地址复制了一份给obj2,因而它们共同指向了一个堆内存对象;
为什么基本数据类型保存在栈中,而引用数据类型保存在堆中?
1)堆比栈大,栈比堆速度快;
2)基本数据类型比较稳定,而且相对来说占用的内存小;
3)引用数据类型大小是动态的,而且是无限的,引用值的大小会改变,不能把它放在栈中,否则会降低变量查找的速度,因此放在变量栈空间的值是该对象存储在堆中的地址,地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响;
4)堆内存是无序存储,可以根据引用直接获取;
按引用访问:js不允许直接访问保存在堆内存中的对象,所以在访问一个对象时,首先得到的是这个对象在堆内存中的地址,然后再按照这个地址去获得这个对象中的值;ECMAScript中所有函数的参数都是按值来传递的,对于原始值,只是把变量里的值传递给参数,之后参数和这个变量互不影响,对于引用值,对象变量里面的值是这个对象在堆内存中的内存地址,因此它传递的值也就是这个内存地址,这也就是为什么函数内部对这个参数的修改会体现在外部的原因,因为它们都指向同一个对象;
2、基本数据类型使用typeof可以返回其基本数据类型,但是NULL类型会返回object,因此null值表示一个空对象指针;引用数据类型使用typeof会返回object,此时需要使用instanceof来检测引用数据类型;
深拷贝和浅拷贝简单解释
浅拷贝和深拷贝都只针对于引用数据类型,浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存;但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象;
区别:浅拷贝只复制对象的第一层属性、深拷贝可以对对象的属性进行递归复制;

深拷贝递归实现
var obj = {
num: 1,
name: '阿七',
msg: {
age: 18
},
color: ['pink', 'red', 'blue']
}
var o = {};
// 封装函数
function deepCopy(newobj, oldobj) {
for (var k in oldobj) {
// 判断我们的属性值是属于那种数据类型
// 1. 获取属性值 oldobj[k]
var item = oldobj[k];
// 2.判断这个值是不是数组
if (item instanceof Array) {
/*
如果是数组的话为在索引为这个位置的 newobj[k] 新建一个空数组
以上面的obj为例子 相当于
newobj[3] = [];
deepCopy(newobj[3], [color]) (个人理解)
*/
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(obj);
console.log(o);
浅拷贝 实现
var obj = {
num: 1,
name: '阿七',
msg: {
age: 18
},
color: ['pink', 'red', 'blue']
}
var o = {};
o = obj
o.age = 20
console.log(obj);
console.log(o);

浙公网安备 33010602011771号