- 基本数据类型和引用数据类型
- 深拷贝和浅拷贝
基本类型 & 引用类型
- 基本数据类型:
undefined、null、Boolean、String、Number、Symbol。 - 引用数据类型:
Object、Array、Date、Function、RegRxp等。
存储方式:
- 基本数据类型:基本数据类型在内存中分别占有固定大小空间,通过按值来访问。
- 引用数据类型:引用数据类型保存在堆内存中,因为值的大小不固定,但是内存地址大小是固定的,所以在栈内存中存放的是该对象的访问地址(以及对象的变量标识符)。当查询引用类型时,先从栈中读取内存地址,再通过地址找到堆中的值,所以叫做按引用访问。
在计算机的数据结构中,栈比堆的运算速度快,Object、Array是一种复杂的结构且都可以增删改查。将他们放在堆中是为了不影响栈的效率。
深拷贝 & 浅拷贝
- 浅拷贝:仅仅拷贝了引用地址,对象的改变会互相影响。
- 深拷贝:深拷贝会拷贝所有的属性,在堆中重新分配内存,互不影响。
使用场景:
浅拷贝:
Object.assign()
将所有可枚举属性的值从一个或者多个源对象复制到目标对象,同时返回目标对象。{...obj}扩展运算符Array.prototype.slice()、Array.prototype.concat()
深拷贝:
JSON.parse(JSON.stringify(obj))
先把一个对象序列化为一个JSON字符串,再反序列化为一个对象
问题:
- 会忽略
undefined、symbol、function - 不能解决循环引用的对象
- 不能正确处理
new Date() - 不能处理正则
jQuery.extend()lodash.cloneDeop()- 深拷贝可以使用递归+浅拷贝实现,浅拷贝时判断属性是否是对象,如果是对象就进行递归操作。
function deepCopy(obj) {
if (typeof obj !== 'object') {
throw new TypeError('类型错误');
}
const targetObj = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if(obj.hasOwnProperty(key)) {
if(obj[key] && typeof obj[key] === 'object') {
targetObj[key] = deepCopy(obj[key]);
}else {
targetObj[key] = obj[key];
}
}
}
}