引用类型才存在深浅拷贝的问题。基本数据类型之间是直接赋值。 浅拷贝:拷贝的是栈内存中的数据。如果是基本数据类型,就直接拷贝了基本变量里面的值。如果是引用类型,则只是拷贝了对象存在栈内存中的地址指针,所以此时指向堆内存中的同一个对象(即会出现一个对象发现变化后,另一个同步发生变化的问题)。
一、浅拷贝示例:
1、基本数据类型:
let x = 100 ;
let y = x;
console.log('x',x)
console.log('y',y)
x= 200
console.log('x',x)
console.log('y',y)
结果:
x 100
y 100
x 200
y 100
2、引用数据类型:
var a = {
name:'小明',
age:18
}
var b = a
console.log(a)
console.log(b)
console.log('a对象被修改后')
a.name='大明'
console.log(a)
console.log(b)
输出结果:
{ name: '小明', age: 18 }
{ name: '小明', age: 18 }
a对象被修改后
{ name: '大明', age: 18 }
{ name: '大明', age: 18 }
二、深拷贝: 浅拷贝因为指向同一个对象,产生了联动修改的效果。所以需要深拷贝,让两个变量指向两个对象。
一、如何实现深拷贝:
1、使用递归:
let people = {
name: 'Tom',
age: 18,
happy:['吃饭','睡觉','打游戏','听歌'],
lover:{
name: 'Amy',
age: 18,
sex:'女'
},
do:function(name){
console.log(this.name+'在打篮球')
}
}
function cloneDeep(obj){
// 如果不是引用类型,直接返回,不需要深拷贝
if(typeof obj != 'object' || obj == null){
return obj
}
let copyObj
if(obj instanceof Array){
copyObj = []
}else
copyObj = {}
for(i in obj){
copyObj[i]=cloneDeep(obj[i])
}
return copyObj
}
let copyPeple = cloneDeep(people)
people.name='tom2号'
people.happy[0]='挨饿'
people.lover['age']=28//people.lover[age]='28':age is not defined
people.lover.name='Nene'
console.log('people',people)
people.do()
console.log('copyPeple',copyPeple)
copyPeple.do()
结果:原对象改变,新对象不受印象。
people {
name: 'tom2号',
age: 18,
happy: [ '挨饿', '睡觉', '打游戏', '听歌' ],
lover: { name: 'Nene', age: 28, sex: '女' },
do: [Function: do]
}
tom2号在打篮球
copyPeple {
name: 'Tom',
age: 18,
happy: [ '吃饭', '睡觉', '打游戏', '听歌' ],
lover: { name: 'Amy', age: 18, sex: '女' },
do: [Function: do]
}
Tom在打篮球
2、JSON.parse(JSON.stringify(被拷贝对象变量名)) 缺点: 缺点,无法实现对对象中方法的深拷贝
let people = {
name: 'Tom',
age: 18,
happy:['吃饭','睡觉','打游戏','听歌'],
lover:{
name: 'Amy',
age: 18,
sex:'女'
},
do:function(name){
console.log(this.name+'在打篮球')
}
}
let copyPeople = JSON.parse(JSON.stringify(people))
people.name='tom2号'
people.happy[0]='挨饿'
people.lover['age']='28'//people.lover[age]='28':age is not defined
people.lover.name='Nene'
console.log(people)
console.log(copyPeople)
people.do()
copyPeople.do()//copyPeople.do is not a function 无法实现对对象中方法的深拷贝
结果
{
name: 'tom2号',
age: 18,
happy: [ '挨饿', '睡觉', '打游戏', '听歌' ],
lover: { name: 'Nene', age: '28', sex: '女' },
do: [Function: do]
}
{
name: 'Tom',
age: 18,
happy: [ '吃饭', '睡觉', '打游戏', '听歌' ],
lover: { name: 'Amy', age: 18, sex: '女' }
}
tom2号在打篮球
TypeError: copyPeople.do is not a function
3、特殊:
3.1、Object.assign
Object.assign(对象a,对象b),把对象b的值,与对象a的值汇总,返回值为对象a。(范围是:所有可枚举属性的值)
// 1、理解Object.assign()例子:
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target);// expected output: Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget);// expected output: Object { a: 1, b: 4, c: 5 }
Object.assign方法作用范围:
1、当对象只有一级属性为深拷贝;
2、当对象中有多级属性时,二级属性后就是浅拷贝
let a = {
name:'kyp',
age:18,
happy:['吃饭','睡觉','打游戏','听歌'],
}
let b = Object.assign({},a)
a.name='kyp被修改了'
// a.happy='写代码'
a.happy[0]='写代码'
console.log(b)
console.log(a)
结果:
{ name: 'kyp', age: 18, happy: [ '写代码', '睡觉', '打游戏', '听歌' ] }
{ name: 'kyp被修改了', age: 18, happy: [ '写代码', '睡觉', '打游戏', '听歌' ] }
3.2、 数组api:concat与slice 个人觉得和Object.assign()挺像的,都是一级属性时就是深拷贝,二级属性及以上就是浅拷贝
let a = [1,2,{name:'kyp'}]
let b = [5,6]
// let b = ['a','b','c','d']
let c = a.concat(b)
a[0]='a'
// a[2]=[7,8]
a[2].name='修改了'
console.log(a);
console.log(c);
结果:
[ 'a', 2, { name: '修改了' } ]
[ 1, 2, { name: '修改了' }, 5, 6 ]