Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

精读《Immer.js》源码 #68

Closed
ascoders opened this issue Mar 13, 2018 · 6 comments
Closed

精读《Immer.js》源码 #68

ascoders opened this issue Mar 13, 2018 · 6 comments

Comments

@ascoders
Copy link
Owner

本周精读的源码是:https://github.com/mweststrate/immer

Immer 出来这么久了,为啥选它?因为最近它越来越火了。。我们当然不想知其然而不知所以然,所以,源码读起来吧~

@ascoders ascoders mentioned this issue Mar 19, 2018
65 tasks
@AsceticBoy
Copy link

你好,我觉得 Immer 中我比较不理解 getter 中为啥有些是需要 (state.copy[prop] = createProxy(state, value)) 而有些需要 (state.proxies[prop] = createProxy(state, value))。可是它最终在 setter 中都是 Object.assign(state.copy, state.proxies) 了,所以他这样做的意义或者优势在哪里

@AsceticBoy
Copy link

是不是因为 proxies 这玩样因为存了属性中已经访问过的代理对象,等再一次访问到同样属性的时候,取的快一点? @ascoders 希望大佬能帮忙解解惑

@ascoders
Copy link
Owner Author

首先记住,所有对象初始值存在 base 属性里,所有修改都不会碰 base,这是 immutable 的最基本原则,改的话放在 copy 里。

基本上说到这就很清楚了,base 存上个状态,copy 存下个状态,proxies 存中间状态(代理对象)。

下面的场景:

produce(draft => console.log(draft.a.b))

produce(draft => {
  draft.a = { b: 1 }
  draft.a.b = 2
  console.log(draft)
})

第一行是直接 getter,全程没有修改过对象,那直接给你代理对象扔到 proxies 里即可,这是最正常的做法。

后面是先修改了 draft.a,再通过 draft.a.b 访问到了 .a 属性,此时 draft 已经被修改过,直接访问 copy,将访问到的属性 proxy 化。至于说此时为什么不访问 proxies 而是 copy? 因为 copy 优先级比 proxies 高,已经修改过了,也就是有了 copyproxies 就不需要了。

所以 markChanged 有这么一段代码:

Object.assign(state.copy, state.proxies)

在任何对象触发 setter 后,把 proxies 赋给 copy(这些 proxies 是 getter 之前生成的),之后就再也不用 proxies 了。

@AsceticBoy
Copy link

AsceticBoy commented Mar 23, 2018

大佬,我想明白了,是我一开始对 proxy 理解的不够到位,draft.a.b = 2 如果没有事先给到 draft.a 的代理对象,draft.a.bsetter 都进不去。更不用说后面的操作了。所以必须要访问的中间态 proxies

@negativeentropy9
Copy link

那 immer.js 的作用只是在改变状态上为重组状态提供了方便呗(不用扩展原状态和生成新引用),存储方式并没有改变,仍然是浅拷贝。

@ponkans
Copy link

ponkans commented May 18, 2023

看作者第一版代码就都比较明确了 https://github.com/immerjs/immer/tree/1b8a694eda1cbbf68196fb74c6d56bc53449924a

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants