请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

关于浅拷贝与赋值

老师,如果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回答

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

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

然后 state1.obj.name = 'lisi'

最后去 setState(state1)

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


-------

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

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

0 回复 有任何疑惑可以回复我~
双越 2021-01-06 22:19:44

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

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

这一点你要搞明白。

0 回复 有任何疑惑可以回复我~
  • 提问者 陌上兮月 #1
    所以对于这种更改嵌套对象的深层对象的某一个属性的场景,老师建议怎么做呢?换指针or浅拷贝or深拷贝。
    
    感觉深拷贝是有点没必要,成本大
    回复 有任何疑惑可以回复我~ 2021-01-06 22:22:53
  • 双越 回复 提问者 陌上兮月 #2
    如果笨拙一点,就是深拷贝。
    成拷贝成本高,所以有了 immutable.js ,这个性能好,它的原理你可以去了解一下,不是笨拙的深拷贝。
    回复 有任何疑惑可以回复我~ 2021-01-06 22:25:02
  • 提问者 陌上兮月 回复 双越 #3
    主要是这种场景,简单使用浅拷贝或者换指针,虽然不是真正意义上的完全彻头彻尾地替换了不可变值,但是看起来运行也很正常。这样是会有什么隐患吗?这点困扰了我很久,望老师解答
    回复 有任何疑惑可以回复我~ 2021-01-06 22:29:50

相似问题

登录后可查看更多问答,登录/注册

问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信