shallow
shallow 让你能对简单的数据结构进行快速检查。当你处理的数据结构内部没有嵌套对象或数组时,它能有效识别顶层属性的变化。
NOTE
shallow 可以做快速比较,但请记住它的局限性。
const equal = shallow(a, b)
类型
签名
shallow<T>(a: T, b: T): boolean
参考
shallow(a, b)
参数
返回值
当 a 和 b 基于其顶层属性的浅比较判定为相等时,shallow 返回 true;否则应返回 false。
用法
比较原始值
在比较 string、number、boolean 和 BigInt 这类原始值时,如果值相同,Object.is 和 shallow 函数都会返回 true。这是因为原始值按实际值比较,而不是按引用比较。
const stringLeft = 'John Doe'
const stringRight = 'John Doe'
Object.is(stringLeft, stringRight) // -> true
shallow(stringLeft, stringRight) // -> true
const numberLeft = 10
const numberRight = 10
Object.is(numberLeft, numberRight) // -> true
shallow(numberLeft, numberRight) // -> true
const booleanLeft = true
const booleanRight = true
Object.is(booleanLeft, booleanRight) // -> true
shallow(booleanLeft, booleanRight) // -> true
const bigIntLeft = 1n
const bigIntRight = 1n
Object.is(bigIntLeft, bigIntRight) // -> true
shallow(bigIntLeft, bigIntRight) // -> true
比较对象
比较对象时,理解 Object.is 和 shallow 函数的工作方式很重要,因为它们处理比较的方式不同。
shallow 函数返回 true,因为 shallow 执行的是对象的浅比较。它会检查顶层属性及其值是否相同。在这个例子中,objectLeft 和 objectRight 的顶层属性(firstName、lastName 和 age)及其值完全相同,所以 shallow 认为它们相等。
const objectLeft = {
firstName: 'John',
lastName: 'Doe',
age: 30,
}
const objectRight = {
firstName: 'John',
lastName: 'Doe',
age: 30,
}
Object.is(objectLeft, objectRight) // -> false
shallow(objectLeft, objectRight) // -> true
比较 Set
比较 Set 时,理解 Object.is 和 shallow 函数的工作方式很重要,因为它们处理比较的方式不同。
shallow 函数返回 true,因为 shallow 执行的是 Set 的浅比较。它会检查顶层属性(在这里就是 Set 本身)是否相同。由于 setLeft 和 setRight 都是 Set 对象的实例,并且包含相同的元素,所以 shallow 认为它们相等。
const setLeft = new Set([1, 2, 3])
const setRight = new Set([1, 2, 3])
Object.is(setLeft, setRight) // -> false
shallow(setLeft, setRight) // -> true
比较 Map
比较 Map 时,理解 Object.is 和 shallow 函数的工作方式很重要,因为它们处理比较的方式不同。
shallow 返回 true,因为 shallow 执行的是 Map 的浅比较。它会检查顶层属性(在这里就是 Map 本身)是否相同。由于 mapLeft 和 mapRight 都是 Map 对象的实例,并且包含相同的键值对,所以 shallow 认为它们相等。
const mapLeft = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
])
const mapRight = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
])
Object.is(mapLeft, mapRight) // -> false
shallow(mapLeft, mapRight) // -> true
疑难解答
对象相同但比较返回 false
shallow 函数执行的是浅比较。浅比较只检查两个对象的顶层属性是否相等,它不会检查嵌套对象或深层嵌套的属性。换句话说,它只比较属性的引用。
在下面的示例中,shallow 函数返回 false,因为它只比较顶层属性及其引用。两个对象中的 address 属性都是嵌套对象,尽管它们的内容完全相同,但引用不同。因此 shallow 认为它们不同,结果就是 false。
const objectLeft = {
firstName: 'John',
lastName: 'Doe',
age: 30,
address: {
street: 'Kulas Light',
suite: 'Apt. 556',
city: 'Gwenborough',
zipcode: '92998-3874',
geo: {
lat: '-37.3159',
lng: '81.1496',
},
},
}
const objectRight = {
firstName: 'John',
lastName: 'Doe',
age: 30,
address: {
street: 'Kulas Light',
suite: 'Apt. 556',
city: 'Gwenborough',
zipcode: '92998-3874',
geo: {
lat: '-37.3159',
lng: '81.1496',
},
},
}
Object.is(objectLeft, objectRight) // -> false
shallow(objectLeft, objectRight) // -> false
如果去掉 address 属性,浅比较就会按预期工作,因为所有顶层属性都会是原始值或指向相同值的引用:
const objectLeft = {
firstName: 'John',
lastName: 'Doe',
age: 30,
}
const objectRight = {
firstName: 'John',
lastName: 'Doe',
age: 30,
}
Object.is(objectLeft, objectRight) // -> false
shallow(objectLeft, objectRight) // -> true
在这个修改后的示例中,objectLeft 和 objectRight 具有相同的顶层属性和原始值。由于 shallow 函数只比较顶层属性,它会返回 true,因为两个对象中的原始值(firstName、lastName 和 age)完全相同。
比较原型不同的对象
shallow 函数会检查两个对象是否具有相同的原型。如果它们的原型在引用上不同,shallow 将返回 false。这个比较通过以下代码完成:
Object.getPrototypeOf(a) === Object.getPrototypeOf(b)
WARNING
使用对象字面量({})或 new Object() 创建的对象默认继承自 Object.prototype。而使用
Object.create(proto) 创建的对象继承自你传入的 proto——它可能并不是 Object.prototype。
const a = Object.create({}) // -> prototype is `{}`
const b = {} // -> prototype is `Object.prototype`
shallow(a, b) // -> false