Hooks与闭包
设计动机
- 解决组件之间状态难以复用的问题
- 让组件更容易理解
hooks 可以理解为更底层的实现,内部会自动帮我们管理状态,不用像ClassComponent
组件一样在生命周期里写各种逻辑。
hooks
能够让函数式组件拥有内部状态的基本原理,就是利用闭包的特性「闭包对象持久存在」。这让函数组件下次执行时能够获取到上次函数执行结束时state
的值。
回顾下闭包的定义:闭包是一个特殊的对象。它由两部分组件,执行上下文 A 以及 A 中创建的函数 B。当 B 执行时,如果访问了 A 中的变量,那么闭包就产生了。
在 chrome 中,执行上下文 A 的函数名代指闭包。
闭包与模块
当我们定义一个 React 组件,并在其他模块在使用,这时候思考一下模块与闭包的关系:
在模 Counter.jsx 中定义一个 Counter 组件
1 | // Counter.jsx |
然后在 App 模块中使用 Counter 组件
1 | // App.jsx |
上面的代码转换成伪代码
1 | const CounterModule = (function() { |
当 App 函数执行时,访问了 AppModule 中定义的变量对象 Counter,那么闭包「Closure[A]」就产生了。
也就说,每一个 JS 模块都可以认为是一个独立的作用域,当代码执行时,该词法作用域创建执行上下文,如果模块内部,创建了可供外部引用访问的函数时,就为闭包的产生提供了条件,只要该函数在外部执行访问了模块内部的其他变量,闭包就会产生。
函数组件本质上就是一个函数,当我们在一个函数组件 A 中导入另一个函数组件 B,并在 A 中执行时 B 时,闭包就会产生。
hooks 与闭包
这是一个很常规的组件,我们用伪代码来分析下
1 | import { useState } from 'react'; |
先看 useState 的伪代码实现
1 | function SM() { |
Demo 模块转为伪代码,代码如下:
1 | // hooks与闭包 |
StateModule 返回 内部函数 myUseState 赋值给 myUseState,myUseState执行时(第 22 行)访问了 StateModule 的 state 变量(第 8 行),此时闭包对象「Closure(SM)」就产生了。
现在我们知道了调用 useState 会产生闭包,那么调用 setState 会不会产生闭包呢?答案是会
可以看到,调用 dispatch 时,闭包对象Closure(SM)
产生了,这个闭包对象保存着上次的 state 结果。