解构赋值是深拷贝吗?

javascript/jquery

浏览数:374

2019-4-19

最近在使用Redux想到一个问题,Redux里常用的一种语法是这样的:

setSth(state, { payload }) {
    const { newthing} = payload;
    return {
        ...state,
        newthing
    }
}

Redux通过解构赋值…state,保留了state里未修改的部分,并覆盖修改的部分,那么现在问题来了,这里的新对象通过解构得来的…state,是否是原来属性的引用赋值呢?

我们知道,如下情况:

let state = {a: 1, b: 2}
let state2 = state;
state2.a = 5;
// state.a === 5 => true

这里state2是state的一个引用赋值。
那么使用解构赋值生成一个新对象会如何呢?

let state = {a: 1, b: 2}
let state2 = { ...state }
state2.a = 5;
// state.a === 1 => true

通过实验可见,state2属性的修改并没有影响到state,所以这是一份拷贝,那么问题又来了,这个拷贝是只有一层的浅拷贝,还是递归进去的深拷贝呢,我直觉地认为是深拷贝,于是又做了一个实验:

let state = {a: {a1: 1, a2: 2}, b: 2}
let state2 = { ...state }
state2.a.a1 = 5;
// state.a.a1 === 5 => true

事实证明我的直觉错了,解构复制到全新对象里只是浅拷贝,对象里属性的属性还是对原来对象里属性的属性的一个引用,因为解构赋值可以生成一份浅拷贝,其实我们针对已知结构的对象也可以全部使用这个方法实现自己想要的拷贝。比如上例中:

let state = {a: {a1: 1, a2: 2}, b: 2}
let state2 = { ...state, a: { ...state.a } }

希望可以帮助大家。