3. Why Immutable / 为毛要不可变
最后更新于:2022-04-01 05:02:02
Immutable 是函数式的概念之一,一旦创建出来之后,就不能再改变。因此,当你想对其做修改,就得弄一个新的。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-11-20_564e9932e7227.gif)
好奇的同学要问了,但是 React 看起来是面向对象的啊。 `createClass` , `state` ,函数式有状态和 class 吗?
> If a tree falls in a forest and no one is around to hear it, does it make a sound? [2](http://blog.oyanglul.us/javascript/react-cookbook-mini.html#fn.2)
首先,函数式和面向对象并不冲突,两种编程范式分别有各自的方式解决问题。
其次:
## 3.1 状态
如果状态只存在于 Component 中又并没有影响任何人,它还是状态吗?
ClojureScript 的 React 库 om,只有一个 app 级别的 state。因此所有的 component,其实并无状态。
[https://youtu.be/5yHFTN-_mOo](https://youtu.be/5yHFTN-_mOo)
## 3.2 Class
想象一下使用一个 React Component 的时候
~~~
<AFancyHelloWord message="Good News Everyone!"/>
~~~
来想象一下
1. 尖括号 `<` 往右移
2. 尖括号变成圆括号
3. 里面再加个大括号
4. 等号变冒号
~~~
AFancyHelloWord({message:"Good News Everyone!"})
~~~
[./images/futurama_August_26__2015_at_0617AM.gif ](http://blog.oyanglul.us/javascript/images/futurama_August_26__2015_at_0617AM.gif)ok, 如果把每个 Component 看成一个函数,为了我们的代码更好 reason about 而且更 loose couple,我们应该尽量要**消除** 每一个 Component 的状态。 这样在 Component 的树中,我们可以随意切换 Component,以 Star Wars 为例,Anakin 有两样东西,Luke 和光剑:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-11-20_564e993329b5a.png)
当 Anakin 变成 Darth Vader,光剑的颜色变红时,Darth Vadar 有 Luke 和 红色光剑。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-11-20_564e993337585.png)
实际上我们需要尽量减少 Component 中的状态,而且对着少数的状态,由于他们是我们的 source of truth,并不希望他是 mutable 的,这样我很难知道谁动了我的 source of truth。
## 3.3 让你的数据结构 immutable 的工具们
### [Immutablility helper](http://facebook.github.io/react/docs/update.html)
这是 react addon 中自带的工具,如果你并不想完整的 Immutable 数据结构,这个工具可以帮助 copy 一份来做改动
~~~
var update = require('react-addons-update');
var inc = x=>x+1
var fancyPropsForChild=update(this.state, {
x: {y: {z: {$set: 7}}},
a: {b: {$push: [9]}},
h: {$merge: {i: "j"}},
e: {$apply: inc}
});
~~~
### [mori](https://github.com/swannodette/mori)
更为彻底的选择是,使用 ClojureScript 的 Immutable 数据结构。benchmark 要比 facebook 的 Immutable.js 好上许多,但是使用上跟 ClojureScript 一致, 用惯JavaScript的人可能不太能习惯,alternative 是使用我 fork 的 mori 版本[conjs](http://github.com/jcouyang/conjs)。
### [Immutable.js](https://facebook.github.io/immutable-js/)
facebook 实现的 immutable 数据结构,使用上比较符合 JavaScript 习惯一些, 不过跑分低一些。