1. 纯函数
所谓纯函数,它是这样一种函数:即相同的输入,永远会得到相同的输出,而且没有任何可观察的副作用。
从纯函数的定义,可以提取出纯函数的必要条件:
- 纯函数接受参数,基于参数计算,返回一个新对象;
- 不会产生副作用,计算过程不会修改输入的参数并且不修改其作用域之外的参数或方法;
- 相同的输入保证相同的输出。
先来看个例子,做下对比:
let friend = {
firstName: 'zhang',
lastName: 'san',
age: 18
}
// 非纯函数:会修改函数外变量 friend 的值
function appendMessage() {
friend.message = {
time: '2021年',
info: '学习React'
}
}
// 纯函数:返回一个新对象,且不会修改参数
function appendMessage(friend) {
let copyFriend = Object.assign({}, friend)
copyFriend.message = {
time: '2021年',
info: '学习React'
}
return copyFriend
}
通过上面的代码,可以总结出纯函数的优点:
- 相同的输入必定是相同的输出,所以纯函数可以根据输入来做缓存;
- 相同的输入必定是相同的输出,这就保证了引用的透明性;
- 纯函数完全自给自足,这点的好处就是纯函数的依赖很明确,因此更易于观察和理解,而且让我们的测试更加容易;
- 可靠:不用担心有副作用,可以更好的工作;
- 代码并行:可以并行运行任意纯函数,因为纯函数不需要访问共享的内存,而且也不会因为副作用而进入竞争态。
所以,建议使用纯函数来编写函数。执行一个纯函数不需要担心它会干什么坏事,它不会产生不可预料的行为,也不会对外部产生影响。不论什么时候,相同的输入必定是产出相同的输出,而且使用纯函数方便我们调试和测试。
2. 纯函数组件
如果一个组件没有状态(state),那么组件的输出方式,将完全取决于两个参数:props
和 context
,只要有相同的 props
和 context
,那么他们的输出绝对是相同的。将组件比喻成函数的话,相同的输入(props
和 context
) 永远都会有相同的输出:
// ...
render(){
return this.props.sayHi ? <div>Hi</div> : <span>Byebye</span>
}
如上面代码所示,props 是输入,只要输入相同,那么输出也一定相同。
使用纯函数创建组件:
// function
function Title (props) {
return <h1>{ props.title }</h1>
}
// 箭头函数
const Title = ({ props }) => <div>{ props.title }</div>
对比下使用类组件方式创建的组件:
// es6 类组件
class Title extends React.Component {
render() {
return <h1>{this.props.title}</h1>
}
}
通过对比,纯函数组件写法简单了,可以看出纯函数组件的特点:
- 组件不会被实例化,整体渲染性能得到提升;
- 组件不能访问 this 对象;
- 组件无法访问生命周期的方法;
- 无状态组件只能访问输入的 props,无副作用。
可以总结出纯函数组件的优点:
- 无副作用;
- 占内存更小,首次 render 的性能更好;
- 语法更简洁,可读性好,逻辑简单,测试简单,代码量少,容易复用;
- 更佳的性能表现:因为函数组件中不需要进行生命周期的管理和状态管理,因此 React 并不需要进行某些特定的检查和内存分配,保证了性能。
当然,纯函数组件也有自己的短板,它无生命周期,且没有 this
。
3. 使用场景
纯函数组件被鼓励在大型项目中尽可能以简单的写法来分割原本庞大的组件,未来 React 也会像面向无状态组件一样在譬如无意义的检查和内存分配领域进行一系列优化,所以只要有可能,尽量使用无状态组件。
纯函数不会产生不可预料的行为,建议合理的选择纯函数的方式书写函数。同样,在 React 组件中,如果无需本地 state 去缓存一些数据,也不需要用到生命周期函数,那么就可以把当前组件定义为纯函数组件,可读性好,且性能表现更佳。