// curried invocation 判断第一个函数是否为函数,如果是函数那么就是柯里化调用 if (typeof baseState === "function") { // prettier-ignore 如果第一个参数是一个函数,那么就是柯里化调用,则第二个函数必定不能为函数(如果第一个参数为函数,第二个参数可以为数组或者对象,作为初始化状态) if (typeof producer === "function") thrownewError("if first argument is a function (curried invocation), the second argument to produce cannot be a function")
// prettier-ignore // 如果第一个参数不是函数,那么就不是柯里化,第二个参数必然是函数 { if (typeof producer !== "function") thrownewError("if first argument is not a function, the second argument to produce should be a function") }
// if state is a primitive, don't bother proxying at all // 如果 原始数据不是数组或者对象,或者为空就不需要代理了 if (typeof baseState !== "object" || baseState === null) { const returnValue = producer(baseState) return returnValue === undefined ? baseState : returnValue }
if (!isProxyable(baseState)) // 如果不是原始对象那么就抛出错误 thrownewError( `the first argument to an immer producer should be a primitive, plain object or array, got ${typeof baseState}: "${baseState}"` ) /** * `getUseProxies 函数判断当前环境是否存在 Proxy 如果存在就使用 Proxy 如果不存在就使用es5方案 */ returngetUseProxies() ? produceProxy(baseState, producer) : produceEs5(baseState, producer) }
阅读文档说明得知 Immer 支持比较旧的 JavaScript 环境, 在比较新的环境下使用性能好的 Proxy ,在比较旧的环境下使用另一种方案先看看 Proxy 方案
/** * isProxy 判断 baseState 是否为空如果不为空 * 判断 baseState中是否存在 __$immer_state(symbol不存在) 属性 * 如果本身已经被代理过了那么直接运行 */ if (isProxy(baseState)) { // See #100, don't nest producers // 详见 #100 不要嵌套 producers const returnValue = producer.call(baseState, baseState) // 调用回调函数,并且将this指向 baseState 本身 return returnValue === undefined ? baseState : returnValue } const previousProxies = proxies // proxies = null proxies = [] try { // create proxy for root // 为 root 创造一个 Proxy // createProxy 接收两个参数, 创建一个 proxy代理对象 const rootProxy = createProxy(undefined, baseState) // execute the thunk // 执行这个被包装过的对象 const returnValue = producer.call(rootProxy, rootProxy) // and finalize the modified proxy // 并最终确认修改后的 proxy let result // check whether the draft was modified and/or a value was returned // 用于检查 draft 是否已经修改或者返回值 if (returnValue !== undefined && returnValue !== rootProxy) { // something was returned, and it wasn't the proxy itself // 确定返回了一些东西,而不是 proxy 本身 if (rootProxy[PROXY_STATE].modified) // 如果没有修改或者没有返回抛出错误 thrownewError(RETURNED_AND_MODIFIED_ERROR)
// See #117 // Should we just throw when returning a proxy which is not the root, but a subset of the original state? // Looks like a wrongly modeled reducer result = finalize(returnValue) } else { result = finalize(rootProxy) } // revoke all proxies // 完成之后撤销 Proxy each(proxies, (_, p) => p.revoke()) return result } finally { proxies = previousProxies } }