前言:
在 React源码解析之updateClassComponent(下) 中提到了PureComponent
的浅比较:
//如果是纯组件的话,用**浅比较**来比较 props/state
if (ctor.prototype && ctor.prototype.isPureReactComponent) {
return (
//浅等于的判断
!shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState)
);
}
接下来就看下shallowEqual()
的源码
一、shallowEqual
作用:
PureComponet
做浅比较的核心function
源码:
import is from './objectIs';
const hasOwnProperty = Object.prototype.hasOwnProperty;
/**
* Performs equality by iterating through keys on an object and returning false
* when any key has values which are not strictly equal between the arguments.
* Returns true when the values of all keys are strictly equal.
*/
//true 为不要更新
//false 为要更新
function shallowEqual(objA: mixed, objB: mixed): boolean {
//同 Object.js()
//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description
//不要更新
if (is(objA, objB)) {
return true;
}
//只要有一个不是 object或为 null 则返回 false,要更新
if (
typeof objA !== 'object' ||
objA === null ||
typeof objB !== 'object' ||
objB === null
) {
return false;
}
const keysA = Object.keys(objA);
const keysB = Object.keys(objB);
//两个 object 的key 数不一样,则返回 false,要更新
if (keysA.length !== keysB.length) {
return false;
}
// Test for A's keys different from B.
//每一个 value 去一一比较是否是浅相等
//能执行到这里,说明两者 key 的长度是相等的
for (let i = 0; i < keysA.length; i++) {
if (
//不通过原型链查找是否有自己的属性
!hasOwnProperty.call(objB, keysA[i]) ||
//判断两值是否相等
!is(objA[keysA[i]], objB[keysA[i]])
) {
//只要没有属性/两个value不等,则返回 false,需要更新
return false;
}
}
//默认返回 true,不需要更新
return true;
}
export default shallowEqual;
解析:
(1) 关于PureComponet
与Component
的区别,请看:
https://zh-hans.reactjs.org/docs/react-api.html#reactpurecomponent
(2) is()
即Object.is()
,React 直接将其实现在代码内部了:
/**
* inlined Object.is polyfill to avoid requiring consumers ship their own
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
*/
function is(x: any, y: any) {
return (
(x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare
);
}
export default is;
关于Object.is()
的作用及用法,请看:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/is
(3) 注意下返回的true/false
因为是 return !shallowEqual()
,所以true
表示不更新,false
表示要更新
(4) 主要分四种情况
① 非对象类型的比较,直接使用is(objA, objB)
判断
② 到 ④ 是对象类型的比较:
② objA/objB
中,只要有一个不是object
或为null
则返回false
③ objA/objB
的keyLength
不一样,则返回false
,此举的目的是简单比较,优化性能
④ 循环比较objA/objB
的每一个value
,判断是否浅相等
针对 ④ 的例子:
对象的value
是非对象类型:
const a={c:1,d:2}
const b={c:1,d:2}
Object.is(a,b) //false
hasOwnProperty.call(b, 'c') //true
Object.is(a['c'], b['c']) //true
对象的value
是对象类型:
const a={c:{e:3},d:2}
const b={c:{e:3},d:2}
hasOwnProperty.call(b, 'c') //true
//可以看到,只能用于浅比较
Object.is(a['c'], b['c']) //false
可以看到,Object.is()
是PureComponet
做浅比较的根本函数。
(完)
网友评论