_.isMatchWith(object, source, [customizer])
145
_.isMatchWith(object, source, [customizer])
_.isMatchWith此方法与isMatch类似,却别是接受自定义比较函数。如果自定义比较函数比较的结果是undefined,那么比较就会使用lodash自己实现的isEqual
参数
object (Object): 需要检查的对象
source (Object): 需要匹配判断的对象
[customizer] (Function): 自定义比较函数
返回值
(boolean): 如果属性匹配返回true,否则false
例子
function isGreeting(value) { return /^h(?:i|ello)$/.test(value); } function customizer(objValue, srcValue) { if (isGreeting(objValue) && isGreeting(srcValue)) { return true; } } var object = { 'greeting': 'hello' }; var source = { 'greeting': 'hi' }; _.isMatchWith(object, source, customizer); // => true
源代码
import baseIsMatch from './.internal/baseIsMatch.js' import getMatchData from './.internal/getMatchData.js' /** * This method is like `isMatch` except that it accepts `customizer` which * is invoked to compare values. If `customizer` returns `undefined`, comparisons * are handled by the method instead. The `customizer` is invoked with five * arguments: (objValue, srcValue, index|key, object, source). * * @since 4.0.0 * @category Lang * @param {Object} object The object to inspect. * @param {Object} source The object of property values to match. * @param {Function} [customizer] The function to customize comparisons. * @returns {boolean} Returns `true` if `object` is a match, else `false`. * @example * * function isGreeting(value) { * return /^h(?:i|ello)$/.test(value) * } * * function customizer(objValue, srcValue) { * if (isGreeting(objValue) && isGreeting(srcValue)) { * return true * } * } * * const object = { 'greeting': 'hello' } * const source = { 'greeting': 'hi' } * * isMatchWith(object, source, customizer) * // => true */ //此方法与isMatch类似,却别是接受自定义比较函数。如果自定义比较函数比较的结果是undefined,那么比较就会使用lodash自己实现的isEqual function isMatchWith(object, source, customizer) { //如果customizer不是function类型,置为undefined customizer = typeof customizer == 'function' ? customizer : undefined return baseIsMatch(object, source, getMatchData(source), customizer)//调用baseIsMatch处理 } export default isMatchWith
getMatchData
import isStrictComparable from './isStrictComparable.js' import keys from '../keys.js' /** * Gets the property names, values, and compare flags of `object`. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the match data of `object`. */ //获取object的属性名(键名),属性值和比较标记(是否适合使用===比较) function getMatchData(object) { const result = keys(object)//获取object的自身可枚举属性组成的数组 let length = result.length//object的自身可枚举属性长度 while (length--) { const key = result[length]//object属性名 const value = object[key]//object属性值 result[length] = [key, value, isStrictComparable(value)]//生成结果数组的元素 } return result } export default getMatchData
baseIsMatch
import Stack from './Stack.js' import baseIsEqual from './baseIsEqual.js' /** Used to compose bitmasks for value comparisons. */ const COMPARE_PARTIAL_FLAG = 1 const COMPARE_UNORDERED_FLAG = 2 /** * The base implementation of `isMatch`. * * @private * @param {Object} object The object to inspect. * @param {Object} source The object of property values to match. * @param {Array} matchData The property names, values, and compare flags to match. * @param {Function} [customizer] The function to customize comparisons. * @returns {boolean} Returns `true` if `object` is a match, else `false`. */ //isMatch的基础实现 function baseIsMatch(object, source, matchData, customizer) { let index = matchData.length//source对象的键,值,和严格比较标识组成的数组的长度,作为循环索引 const length = index const noCustomizer = !customizer//是否没有传递自定义比较函数 if (object == null) {//如果object是null,判断source的属性长度作为结果 return !length } let data let result object = Object(object) while (index--) {//循环source属性长度 data = matchData[index]//当前matchData if ((noCustomizer && data[2]) ? data[1] !== object[data[0]] : !(data[0] in object) //如果没有自定义比较函数并且适合严格比较,就直接严格比较 //否则用in操作符判断object对象里有没有source对应的键 ) { return false//没有或者不匹配就返回false } } while (++index < length) {//经过一轮适合严格比较和in操作符比较后,索引从长度变为了0,再次从0开始循环到长度,深度比较是否相等 data = matchData[index]//当前matchData const key = data[0]//当前source对象键 const objValue = object[key]//对应object对象的值 const srcValue = data[1]//当前source对象值 if (noCustomizer && data[2]) {//如果没有自定义比较函数并且适合严格比较 if (objValue === undefined && !(key in object)) {//判断object对应值是否是undefined或者object不存在对应key,如果是,就返回false return false } } else {//不适合严格比较或者有自定义比较函数的处理 const stack = new Stack//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 )) {//否则调用baseIsEqual处理 return false } } } return true } export default baseIsMatch