浅拷贝遇到的一些问题
phy-lei 2021-01-23
前端的那些事儿
# 浅拷贝
相信很多人都知道浅拷贝的含义,来自MDN的官方说法:新的对象复制已有对象中非对象属性的值和对象属性的引用。如果这种说法不理解换一种一个新的对象直接拷贝已存在的对象的对象属性的引用,即浅拷贝。
# 浅拷贝的例子
让我们看看最基本的一个浅拷贝吧。
var a = {name:'kiana'}
var b = a
a.name = 'yayi'
console.log(a,b) // {name:'yayi'}
因为对象属于引用数据类型,存的是地址,所以修改这个对象里的name,也相当于修改该地址指向的同一个对象,所以a和b都会变,这大家都知道。然后我们看另外一个例子,变一下:
var a = {name:'kiana'}
var b = a
a = 'yayi'
console.log(a,b) // 'yayi' {name:'kiana'}
这里就会不变,这里看起来就像是深拷贝了一样,这就是我所说的浅拷贝的一些问题,仔细思考,实际上这也是遵循浅拷贝的。为什么我修改了a的值,b还是之前的值呢,这似乎看起来,他们存的地址都不一样了,而修改a.name就会改变name的值,其实,仔细看,我们首先定义了b=a,a的引用是RHS右查询,查到a是{name:'kiana'}这个东西,这个是对象的数据类型,也是引用数据类型,所以说我们其实复制的是这一份{name:'kiana'},而不是变量a,而操作变量a去重新赋值,执行LHS左引用,找到这个变量a去执行赋值,并没有操作到右边的{name:'kiana'},也就没有改变到地址的值,所以这是正确的浅拷贝,并不是错误的。
再看一下数组的情况:
var o = [1,2,3]
var arr = [{"a": []}]
arr[0].a = o
o = 123
console.log(arr); //[1,2,3]
// 如果执行push
var o = [1,2,3]
var arr = [{"a": []}]
arr[0].a = o
o.push(4)
console.log(arr); //[1,2,3,4] push操作了右边的数组,也会改变地址的值
所以,这里提的一些问题,主要是看清变量引用的是什么,操作的是哪一个,不然很容易混乱的。