详谈JavaScript深浅拷贝
为什么?
什么是拷贝:复杂粘贴
为什么分深浅拷贝:
- JavaScript里面的数据存储分为两种:
- 简单数据类型:存储在栈里面
- 复杂数据类型:地址存在栈里面,数据存储在堆里面
- 而复杂粘贴是在操作栈里面的数据
需要使用的数据:
let obj = {
name: 'JavaScript',
age: 25,
type: [
'弱类型',
'解释型',
'脚本语言'
]
}
回到顶部 目录
浅拷贝
第一种方式:利用循环的方式
let copyObj = {};
// 浅拷贝
for(const key in obj){
copyObj[key] = obj[key]
}
第二种方式:利用Object.assign
let copyObj = {};
// 浅拷贝
// 第一个参数是目标对象 copyObj
// 其他参数都为拷贝对象 obj
Object.assign(copyObj, obj)
修改copyObj对象看obj有什么变化:
// 图一
console.log('obj', obj);
console.log('copyObj', copyObj);
copyObj.name = 'Python'; // 没有影响
copyObj.type.push('脚本语言'); // 有影响
copyObj.eat = false; // 没有影响
// 图二
console.log('obj', obj);
console.log('copyObj', copyObj);
分析:
- 浅拷贝:其实拷贝的是栈里面的内容(name没有发生改变,而type同时发生修改了)
- 对于没有复杂类型的数据就可以采用此方法
回到顶部 目录
深拷贝
第一种方法:JSON.parse(JSON.stringify())
let copyObj = {};
copyObj = JSON.parse(JSON.stringify(obj));
- 用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝
第二种方法:自定义方法来实现:deepCodeObjec
let copyObj = {};
function deepCodeObjec(fromObj){
let toObj;
// 在函数中先检查第一个参数是否有值
// 如果没有直接返回一个空对象
if (checkedType(fromObj) === 'Object') {
toObj = {};
} else if (checkedType(fromObj) === 'Array') {
toObj = [];
} else {
return fromObj;
}
for(const key in fromObj){
let fromValue = fromObj[key];
if(checkedType(fromValue) === 'Object' || checkedType(fromValue) === 'Array'){ // 如果是复杂类型就递归调用,再来一次
toObj[key] = deepCodeObjec(fromValue);
}else{ // 如果不是就自己复制
toObj[key] = fromValue;
}
}
return toObj;
}
// 定义检查数据类型的功能函数
function checkedType(param) {
return Object.prototype.toString.call(param).slice(8, -1);
}
copyObj = deepCodeObjec(obj);
- 递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝
修改copyObj对象看obj有什么变化:
copyObj.name = 'Python'; // 没有影响
copyObj.type.push('脚本语言'); // 没有影响
console.log('obj', obj);
console.log('copyObj', copyObj);
分析:
- JSON.parse(JSON.stringify()):这种方法虽然可以实现数组或对象深拷贝,但不能处理函数。
回到顶部 目录