JS中数据类型可以分为基本数据类型和引用数据类型
-
基本数据类型:直接存储在栈(stack)中的数据
-
引用数据类型:引用数据类型在栈中存储了指针,该指针指向堆中该实体的 起始地址 ,真实的数据存放在堆内存里。当解释器寻找引用值时,会首先检索其在栈中的 地址 ,取得地址后从堆中获得实体。
1 深拷贝和浅拷贝区别
浅拷贝 只复制指向某个对象的指针而不复制对象本身,新旧对象还是共享同一块内存。
但 深拷贝 会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
- 当我们把一个对象赋值给一个新的变量时, 赋的其实是该对象的在栈中的地址,而不是堆中的数据 。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。
- 浅拷贝是按位拷贝对象, 它会创建一个新对象 ,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。
2. 浅拷贝实现
(1) Object.assign()
Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是 Object.assign()进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。
var obj = { a: {a: "kobe", b: 39} };
var initalObj = Object.assign({}, obj);
initalObj.a.a = "wade";
console.log(obj.a.a); //wade
注意: 当object只有一层的时候,是深拷贝
let obj = {
username: 'kobe'
};
let obj2 = Object.assign({},obj);
obj2.username = 'wade';
console.log(obj);//{username: "kobe"}
(2) Array.prototype.concat()
let arr = [1, 3, {
username: 'kobe'
}];
let arr2=arr.concat();
arr2[2].username = 'wade';
console.log(arr);// [1,3,{username: 'wade'}]
(3) Array.prototype.slice()
let arr = [1, 3, {
username: ' kobe'
}];
let arr3 = arr.slice();
arr3[2].username = 'wade'
console.log(arr);// [1,3,{username: 'wade'}]
3 深拷贝实现
(1) JSON.parse(JSON.stringify(obj))
var arr = ['old', 1, true, ['old1', 'old2'], {old: 1}]
var new_arr = JSON.parse( JSON.stringify(arr) );
缺点:不能应用于函数类型、Symbol类型、undefined以及循环引用等属性的拷贝
(2) 手写代码实现
const isComplexType = obj => (typeof obj === 'object' || typeof obj === 'function')&&(obj !==null)
const deepClone = function (obj,hash = new Map()){
if(obj.constructor === Date){
return new Date(obj)
}
if(obj.constructor === RegExp) return new RegExp(obj)
if(hash.has(obj)) return hash.get(obj)
let allDesc = Object.getOwnPropertyDescriptors(obj)
let cloneObj = Array.isArray(obj) ? [] : Object.create(Object.getPrototypeOf(obj), allDesc);
hash.set(obj,cloneObj)
for(let key of Reflect.ownKeys(obj)){
cloneObj[key] = (isComplexType(obj[key]) && typeof obj[key] !=='function')?
deepClone(obj[key],hash):obj[key]
}
return cloneObj
}