为何Redux Action采用函数实现而非类?
很棒的问题!其实Redux在设计初期确实考虑过类的方式,但最终选择了函数返回普通对象的模式,主要有这几个关键原因:
简洁性与低心智负担
函数式的Action创建写法要简洁得多,不需要定义类、通过new实例化,少了很多模板代码。对比一下:
函数式写法(现在甚至可以用箭头函数简化):const ACTION_INCREMENT = 'INCREMENT'; const increment = (amount) => ({ type: ACTION_INCREMENT, amount }); store.dispatch(increment(2));类式写法:
class ActionIncrement { constructor(amount) { this.type = 'INCREMENT'; this.amount = amount; } } store.dispatch(new ActionIncrement(2));前者更直接,写起来快,读起来也一目了然。
序列化与调试友好
Redux的核心特性之一是时间旅行调试,这要求Action必须是可序列化的普通对象。类实例在被序列化成JSON时,会丢失原型链上的信息——比如JSON.stringify(new ActionIncrement(2))只会得到{"amount":2},丢失了用来识别Action类型的关键标识;而函数返回的普通对象{type: 'INCREMENT', amount:2}序列化后能完整保留所有信息,方便存储、回放和调试。契合函数式编程理念
Redux本身是基于函数式编程思想构建的,纯函数返回普通对象的模式更符合这种范式。纯函数没有副作用,输入相同输出就完全相同,更容易测试、预测行为,也更符合Redux追求的“状态可预测”目标。而类涉及到实例化和状态封装,带有面向对象的特性,和Redux的函数式核心不太匹配。生态兼容性
Redux社区的大量中间件(比如Redux Thunk、Redux Saga)都是围绕“普通对象Action”设计的。如果用类实例作为Action,很多中间件需要额外处理才能识别Action类型,会增加不必要的复杂度。而普通对象的type字段是约定俗成的标准,所有生态工具都能直接支持。
当然,如果你个人觉得类的写法更符合直觉,也不是完全不能用——只要在Reducer里通过action instanceof ActionIncrement来识别类型就行,但这样会失去Redux带来的序列化调试、生态工具无缝兼容等优势,所以社区很少这么做。
内容的提问来源于stack exchange,提问作者Alvaro Maceda

