1/** 浅复制 */
2function shallowCopy(value) {
3 if (Array.isArray(value))
4 return value.slice()
5 if (value.__proto__ === undefined)
6 return Object.assign(Object.create(null), value)
7 return Object.assign({}, value)
8}
9
10function createState(target) {
11 this.modified = false // 是否被修改
12 this.target = target // 目标对象
13 this.copy = undefined // 拷贝的对象
14}
15
16createState.prototype = {
17 // 对于get操作,如果目标对象没有被修改直接返回原对象,否则返回拷贝对象
18 get(key) {
19 if (!this.modified)
20 return this.target[key]
21 return this.copy[key]
22 },
23
24 // 对于set操作,如果目标对象没被修改那么进行修改操作,否则修改拷贝对象
25 set(key, value) {
26 if (!this.modified)
27 this.markChanged()
28 return (this.copy[key] = value)
29 },
30
31 // 标记状态为已修改,并拷贝
32 markChanged() {
33 if (!this.modified) {
34 this.modified = true
35 this.copy = shallowCopy(this.target)
36 }
37 },
38}
39
40const PROXY_STATE = Symbol('proxy-state')
41
42// 接受一个目标对象和一个操作目标对象的函数
43function produce(state, producer) {
44 const store = new createState(state)
45 const proxy = new Proxy(store, {
46 get(target, key) {
47 if (key === PROXY_STATE)
48 return target
49 return target.get(key)
50 },
51 set(target, key, value) {
52 return target.set(key, value)
53 },
54 })
55
56 producer(proxy)
57
58 const newState = proxy[PROXY_STATE]
59 if (newState.modified)
60 return newState.copy
61 return newState.target
62}
63
64const baseState = [
65 { todo: 'Learn typescript', done: true },
66 { todo: 'Try immer', done: false },
67]
68
69const nextState = produce(baseState, (draft) => {
70 draft.push({ todo: 'Tweet about it', done: false })
71 draft[1].done = true // 这里会改到原属性
72})
73
74console.log(baseState, nextState)