原文:what-is-my-statejavascript
阅读前须知前端
lens
和 atom
等。在我给出个人口味前,下面几个矛盾,你会怎么选择?java
Most papers in computer science describe how their author learned what someone else already knew. — Peter Landingit
在赞美 Calmm 以前,咱们须要达成一些共识github
但愿我们能从一个崭新的角度讨论 state ?算法
值、索引和时间相互交织,索引和时间尤为复杂。typescript
key
通常的语言 (好比 js)对 state 这种数据基本都不作原生支持。编程
这体如今,在这些语言中:框架
这个说法对应于首类元素 first-class
,它ide
没法(随着时间)响应变化
let x = 1 // 建立了一个可变的 state let y = 2 let sum = x + y // 获取了 state 的快照 snapshot,值为 3 x = 3 sum // 值仍是 3,sum 没法观察 x 赋值后的值,随之变化值为 5
state 不是语言中的 first-class
元素
function foo() { let x = 1 // 建立可变的 state bar(x) // 没法将 state 做为参数传递,只能传递值,即 1 x = 2 // 修改了 state ,但这对于函数 bar 来讲是不可知的 return x // 也没法将 state 做为返回,只能返回值,即 2 }
若是你了解 js ,知道变量区分值类型和引用类型、形参实参的分别,那么就不会以为上面的代码有任何奇怪的地方。甚至你会以为若是 x 从新赋值后, sum 会随之变化为 五、对已经调用完毕的 bar 还能产生影响,那才太可怕了。
但其实上面的代码,并非在挑战这些东西。而是假设咱们建立的
x
都是一种名为state
的首类元素,它应当能够
- 做为函数的参数或返回值进行传递,而不只仅只是传递其计算值,即知足其身为 first-class 的特性
- 能够被其它引用它的函数或对象观察到它的变化
固然,目前 js 中并不存在这样的首类元素。
neta
Make American Great Again
, 哈哈
咱们试试在 js 中模拟出 State
下文代码都是 typescript
interface State<T> { get(): T; set(value: T): void; }
咱们已经说过首类元素的特性了,能够做为函数的参数和返回值传递。
class Atom { constructor(value) { this.value = value } get() { return this.value } set(value) { this.value = value } }
如今在组件中,咱们就能够声明一个 state 来做为参数了。
Observable state
class Atom { constructor(value) { this.value = value this.observers = [] } get() { return this.value } set(value) { this.value = value this.observers.forEach(observer => observer(value)) } subscribe(observer) { observer(this.get()) this.observers.push(observer) } }
state 能独立于时间变化了(Independence from time)
decomposable
class LensedAtom { constructor({getter, setter}, source) { this.getter = getter this.setter = setter this.source = source } get() { return this.getter(this.source.get()) } set(value) { this.source.set(this.setter(value, this.source.get())) } }
把 store state 做为一个总体,而其分片的元素做为组件的 state
class PairAtom { constructor([lhs, rhs]) { this.lhs = lhs this.rhs = rhs } get() { return [this.lhs.get(), this.rhs.get()] } set([lhs, rhs]) { this.lhs.set(lhs) this.rhs.set(rhs) } }
通常咱们认为 stream 是无状态的,可是请看:
merge
+ scan
引入了局部状态不过,从好的方便来讲:
可使得依赖更精确:能够方便地观察「是什么触发了这个 stream ?」。
是的,在咱们的方案里,任何人获得了一个 state 的分片,均可以修改它。
可是在 calmm 中,咱们已经