# baseIsMatch
# Description
来判断 object 是否包含 source 的属性,并且属性值相等
# Params
(object, source, matchData, customizer)
{Object} object - 检查对象
{Object} source - 属性值要匹配的对象。
{Array} matchData - 属性名称,值和比较标志以匹配
{Function} [customizer] - 自定义比较函数
# Return
Boolean
# Depend
import Stack from './Stack.js'
import baseIsEqual from './baseIsEqual.js'
# Code
/** Used to compose bitmasks for value comparisons. */
const COMPARE_PARTIAL_FLAG = 1
const COMPARE_UNORDERED_FLAG = 2
function baseIsMatch(object, source, matchData, customizer) {
let index = matchData.length
const length = index
const noCustomizer = !customizer
if (object == null) {
return !length
}
let data
let result
object = Object(object)
while (index--) {
data = matchData[index]
if ((noCustomizer && data[2])
? data[1] !== object[data[0]]
: !(data[0] in object)
) {
return false
}
}
while (++index < length) {
data = matchData[index]
const key = data[0]
const objValue = object[key]
const srcValue = data[1]
if (noCustomizer && data[2]) {
if (objValue === undefined && !(key in object)) {
return false
}
} else {
const stack = new Stack
if (customizer) {
result = customizer(objValue, srcValue, key, object, source, stack)
}
if (!(result === undefined
? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)
: result
)) {
return false
}
}
}
return true
}
# Analyze
首先定义了常量标识符,1 表示部分比较,2表示无序对象
matchData
等同于每一项都为[key, value, isStrictComparableFlag]
的二维数组获取到
matchData
的length
,如果object
为null
或者undefined
,并且matchData.length
也为0,则返回false
,否则返回true
,认为二者相等如果没有传入自定义比较函数,并且
data[2]
为true
,即代表可以使用===
进行判断此时,会比较
data[1] !== object[data[0]]
也就是说,如果
source
对应的value
和object
对应的value
不同,则返回false
如果传入了 自定义比较函数,或者
data[2]
为false
,则使用以下对比逻辑!(data[0] in object)
判断 当前
key
是否在object
原型及其原型链上存在,如果不存在,也返回false
会循环比较以上4,5逻辑,如果不匹配,则直接返回
false
值的对比
while (++index < length) {
data = matchData[index]
const key = data[0]
const objValue = object[key]
const srcValue = data[1]
if (noCustomizer && data[2]) {
if (objValue === undefined && !(key in object)) {
return false
}
} else {
const stack = new Stack
if (customizer) {
result = customizer(objValue, srcValue, key, object, source, stack)
}
if (!(result === undefined
? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)
: result
)) {
return false
}
}
}
值的对比也是 while
循环,进行比较
当没有传入自定义比较函数,并且 data[2]
为 true
时
if (noCustomizer && data[2]) {
if (objValue === undefined && !(key in object)) {
return false
}
}
这里会判断,当前 object
对应的 key
是否为 undefined
,如果为 undefined
,则判断当前 key
是否在 object
及其原型链上存在,如果即为 undefined
,并且不在 object
及其原型链上 存在,则 返回 false
传入了自定义函数,或者 data[2]
为 false
const stack = new Stack
if (customizer) {
result = customizer(objValue, srcValue, key, object, source, stack)
}
if (!(result === undefined
? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)
: result
)) {
return false
}
这里会判断,是传入了自定义函数,如果传入了,则将 result
置为 自定义函数处理的结果,有可能为 undefined
接着会判断,如果 result
为 undefined
,则会使用 baseIsEqual
来进行比较,这里传入了标识,既是部分比较,同时也是无序比较
紧接着会判断比较的结果,如果为 false
,则返回 false
,证明 object
上不完全包含 source
的属性
- 如果以上所有的判断逻辑都过了,则证明
object
上包含source
的属性,并且值相等
# Remark
-
如果指定的属性在指定的对象或其原型链中,则in 运算符返回 true
# Example
const a = {a: 1, b: 1}
const b = {b: 1}
console.log(baseIsMatch(a, b, [['b', 1, true]])) // true