_.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

 

posted @ 2019-01-06 20:08  hahazexia  阅读(304)  评论(0)    收藏  举报