基本数据类型:number string boolean null undefined symbol,存在栈内存
引用数据类型:array object,引用地址储存在栈内存,真实数据储存在堆内存
浅拷贝:
若拷贝的是基本数据类型,则是拷贝基本数据类型的值,存于栈内存中;
若拷贝的是引用数据类型,则是拷贝的是引用地址,共享引用地址,修改引用地址影响原有数据。引用地址存在栈内存,对象存在堆内存。若第一层为基本数据类型,修改值不影响原数据。
深拷贝:
若拷贝的是基本数据,拷贝的是基本数据类型的值,存于栈内存中;
若拷贝的是引用数据类型,则对象的属性值及引用地址全部拷贝,创建一个新对象,不影响原有数据。存放在一新的栈内存中。
浅拷贝
浅拷贝:(Object.assign({},obj), 解构{...})
// A为赋值,不是浅拷贝,赋值后的对象和原对象指向同一对象,第一层数据是基本数据类型,改变后影响原数据,会使原数据改变
// 浅拷贝会创建一个新的对象,与原对象不是同一对象,第一层是基本数据类型时改变后,不影响原数据
let a ={
name:'zs',
age:20
}
let b = a
b[age] = 25
// B: 可以拷贝第一层
Object.assign( { }, obj )
// C:解构
let newObj = { ... obj }
// D: for in
let obj = {
name: 'Yvette',
age: 18,
hobbies: ['reading', 'photography']
}
let newObj = {};
for(let key in obj){
newObj[key] = obj[key]; //赋值操作,两个属性值指向同一个内存空间
}
console.log(newObj);//{ name: 'Yvette', age: 18, hobbies: [ 'reading', 'photography' ] }
obj.age = 20;
obj.hobbies.pop();
console.log(newObj);//{ name: 'Yvette', age: 18, hobbies: [ 'reading' ] }
深拷贝
深拷贝:
// A:数组:使用slice,concat实现深拷贝,
// slice返回一个数组的深拷贝,改变新数组不影响原数组,concat合并数组,并生成一个新的数组,不会影响原数组
let arr1 = [1,2,3,4,5,6]
let arr2 = arr1.slice(1)
console.log(arr2); //[2, 3, 4, 5, 6]
arr2.push(90)
console.log(arr1)//再向arr2中添加数据,arr1未发生变化,实现了深拷贝==》[1, 2, 3, 4, 5, 6]
console.log(arr2)//[2, 3, 4, 5, 6, 90]
// B:使用JSON.parse 与JSON.stringify对引用类型实现深拷贝
let obj1 = {
name : 'ls',
age:10
}
let obj2 = JSON.parse(JSON.stringify(obj1))
console.log(obj2);
obj2['jump'] = 'tt'// 在obj2中添加新属性
console.log(obj1);// {name: "ls", age: 10},obj1未发生让那个变化,则实现了深拷贝,添加新属性未影响源数据
console.log(obj2);// {name: "ls", age: 10, jump: "tt"}
// C:使用递归实现深拷贝
// 对象实现深拷贝原理:定义一个新对象,遍历访问原对象属性,并赋值给新对象
function deepClone(obj) {
let newObj = Array.isArray(obj) ? [] :{} //定义一个新对象
if(newObj && typeof obj === 'object') { //判断原数据类型,原数据是引用数据类型则进入代码块
for(let key in obj) { //遍历原对象
if(obj.hasOwnProperty(key)) { // 先从原对象自身查找属性进行赋值
if(typeof obj[key] === 'object') { // 判断原数据属性的类型,是引用类型继续遍历,不是引用类型则赋值
newObj[key] = deepClone(obj[key])
} else {
newObj[key] = obj[key]
}
}
}
}
return newObj
}