在shouldComponentUpdate中如何对this.props和nextProps进行深度比较?
关于props序列化比较方案的说明
JSON.stringify(this.props) === JSON.stringify(nextProps)这种方案无法正确处理值为函数类型的props
序列化比较方案的缺陷
JSON序列化规则会自动忽略值为函数、undefined、Symbol类型的字段,如果两个props中同一个key对应不同的函数,序列化后该字段都会被丢弃,最终比较结果会错误判定为相等,完全不符合预期。除此之外该方案还有多个常见坑:
- 遇到包含循环引用的对象会直接抛出异常
- Date、RegExp等特殊内置类型的实例序列化后会转为字符串/普通对象,无法区分实例引用差异
- NaN、Infinity等数值会被序列化为
null,会出现NaN和Infinity被判定为相等的错误
可行的替代实现方案
1. 浅层全等比较(最常用)
这也是React.memo、shouldComponentUpdate默认使用的比较逻辑,实现逻辑如下:
- 先判断两个props是否本身全等,全等则直接返回true
- 统计两个props的key数量,数量不等则返回false
- 遍历所有key,逐个比较对应值是否全等(
===),所有值都相等则返回true,否则返回false
优势:性能极高,能正确处理函数类型的props(直接比对函数引用),适配90%以上的业务场景。
示例实现代码:
function shallowEqual(objA, objB) { if (objA === objB) return true if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) { return false } const keysA = Object.keys(objA) const keysB = Object.keys(objB) if (keysA.length !== keysB.length) return false for (let key of keysA) { if (!objB.hasOwnProperty(key) || objA[key] !== objB[key]) { return false } } return true }
2. 深层全等比较
如果props包含嵌套的对象、数组,且需要比对嵌套内容而非引用,可以使用深层比较方案,注意需要额外处理函数、循环引用、特殊内置类型的判断逻辑。
优势:可以满足嵌套结构的内容比较需求,缺点是性能比浅层比较差,适合props嵌套层级不超过3层的场景。
3. 自定义比较逻辑
针对组件的实际业务场景编写专属比较逻辑,比如某个函数prop的引用变化不影响渲染即可跳过比对,某个对象prop只需要比对指定的几个关键字段。
优势:性能最优,完全贴合业务需求,不会出现多余的比对判断。
内容的提问来源于stack exchange,提问作者Uma Maheswar
相关产品推荐
相关产品推荐

