ReactのReact.PureComponentとReact.memoの浅い比較
/**
*
* @param {props || state} objA
* @param {nextProps || nextState} objB
*/
var address = [10, 20]
var a = {
name: 'jack',
age: 25,
address: address
}
var b = {
name: 'jack',
age: 25,
address: address
}
//上記の2つのオブジェクトが同じであると考える
var c = {
name: 'jack',
age: 25,
address: [10, 20]
}
var d = {
name: 'jack',
age: 25,
address: [10, 20]
}
//アドレス参照が異なるので、上記の2つのオブジェクトは同じではないと考えましょう。
2つのオブジェクトが同じである // 2つのオブジェクトが同じであることを意味します:2つのオブジェクトが同じ数の属性を持っており、2つのオブジェクトが同じ属性を持っており、2つのオブジェクトが同じ属性値を持っている、属性値が同じである // 同じ参照を参照し、同じことの中にこれらの2つのオブジェクトの深さ比較ではなくなり、浅い比較です。
function shallowEqual(objA, objB) {
if (Object.is(objA, objB)) { //reactオブジェクト.isポリフィルを行う
return true //こちら側は2つの基本データ型と比較することができ、2つのオブジェクトの参照が同じであることは真とみなされる。
}
//一方がオブジェクト・データ型でない限り、falseを返し、再度比較する必要はない。
if (typeof objA !== 'object' || typeof objB !== 'object'
|| typeof objA === 'null' || typeof objB === 'null'
) {
return false
}
//ここでは、obja, objbがオブジェクトのデータ型であると判断し、その2つが同じかどうかを判断することができる。
var objAkeys = Object.keys(objA)
var objBKeys = Object.keys(objB)
if (objAkeys.length !== objBKeys.length) {
return false
}
//両者が同じでない属性を持つか、属性の値が同じでない限り、両者は不平等とみなされる。
for (let i = 0; i < objAkeys.length; i++) {
if (!objB.hasOwnProperty(objAkeys[i]) || !Object.is(objA[objAkeys[i]], objB[objBKeys[i]])) {
return false
}
}
return true //ここまでは、2つのオブジェクトが同じ属性と同じ属性値を持つことを意味する
}
// 実際にはオブジェクト.is()のポリフィルは
function is(x, y) {
// SameValue algorithm
if (x === y) {
// +0 != -0
return x !== 0 || 1 / x === 1 / y;
} else {
// NaNの処理 === NaN
return x !== x && y !== y;
}
};
console.log(shallowEqual(a, b)) //true
console.log(shallowEqual(c, d)) //false
//深い比較
function deepEqual(objA, objB) {
if (Object.is(objA, objB)) {
return true //こちら側は2つの基本データ型と比較することができ、2つのオブジェクトの参照が同じであることは真とみなされる。
}
//一方がオブジェクト・データ型でない限り、falseを返し、再度比較する必要はない。
if (typeof objA !== 'object' || typeof objB !== 'object'
|| typeof objA === 'null' || typeof objB === 'null'
) {
return false
}
//ここでは、obja, objbがオブジェクトのデータ型であると判断し、その2つが同じかどうかを判断することができる。
var objAkeys = Object.keys(objA)
var objBKeys = Object.keys(objB)
if (objAkeys.length !== objBKeys.length) {
return false
}
//両者が同じでない属性を持つか、属性の値が同じでない限り、両者は不平等とみなされる。
for (let i = 0; i < objAkeys.length; i++) {
if (!objB.hasOwnProperty(objAkeys[i]) || !Object.is(objA[objAkeys[i]], objB[objAkeys[i]])) {
return false
} else {
if (!deepEqual(objA[objAkeys[i]], objB[objAkeys[i]])) {
return false
}
}
}
return true //ここまでは、2つのオブジェクトが同じ属性と同じ属性値を持つことを意味する
}
console.log(deepEqual(a, b)) //true
console.log(deepEqual(c, d)) //true