关于浅拷贝与赋值

来源:7-10 setState为何使用不可变值

陌上兮月

2021-01-06

老师,如果state是引用类型,我们可以用...来做浅拷贝,然而对于深层嵌套的对象来讲,浅拷贝的对象里存放的仍然是指针。也就是说,通过一个浅拷贝的对象去改深层对象的属性,实际上改的是堆内存中的同一个地址。

constructor(props) {
    super(props);
    this.state = {
      count: 0,
      obj: {name: 'zhangsan'},
    }
  }

increase = () => {
    const shallowCopy = { ...this.state };
    setTimeout(() => {
      shallowCopy.obj.name = 'lisi';
      console.log(this.state); // 其实这里state.obj.name已经变为lisi了
      this.setState(shallowCopy);
    })
  }

又或者,甚至不做浅拷贝,直接换指针,也没报错。

increase = () => {
    const anotherPointer = this.state;
    setTimeout(() => {
      anotherPointer.obj.name = 'lisi';
      console.log(this.state); // 这里state.obj.name也已经变为lisi了
      this.setState(anotherPointer);
    })
  }

所以,不可变值对于嵌套多的引用类型来说,是不是只要换个指针重新赋值就行了?(甚至不需要做浅拷贝)。

毕竟,一个嵌套多层的对象,更改了比如info.basic.name这样一个深层属性,应该不需要把整个info对象深拷贝一遍再替换原来的吧?

看起来只需要换个指针就能欺骗react了。

写回答

2回答

双越

2021-01-07

你这个场景决定的,其实不用你的“浅拷贝或者换指针”。

你直接取出 state 即 const state1 = this.state 

然后 state1.obj.name = 'lisi'

最后去 setState(state1)

这样做也是正常的,你可以试一下。


-------

因为你的场景中,并没有用 PureComponent 或者做 SCU 优化,所以每次 setState 都会无条件重新渲染。

所以,无论你怎么折腾,它都是正常的。

0
0

双越

2021-01-06

你不是要“欺骗”React ,你是要“欺骗”js 引擎。

因为深拷贝、浅拷贝这些,不是 React 独创的,它本身就是 js 的逻辑。

这一点你要搞明白。

0
3
陌上兮月
回复
双越
主要是这种场景,简单使用浅拷贝或者换指针,虽然不是真正意义上的完全彻头彻尾地替换了不可变值,但是看起来运行也很正常。这样是会有什么隐患吗?这点困扰了我很久,望老师解答
2021-01-06
共3条回复

2024版 前端框架及项目面试 聚焦Vue3/React/Webpack

面向1-3年前端的框架及项目面试“刚需内容”

4663 学习 · 1644 问题

查看课程