isMatch.js

import allKeys from './allKeys';
import getTag from './internals/getTag';
import { nativeUndefined, objectTag } from './internals/native';
import isEqualDeep from './internals/isEqualDeep';
// 是否需要深比较
function isDeepComparable(object, source) {
    return getTag(object) === objectTag && getTag(source) === objectTag;
}
function baseIsMatch(object, source, customizer, strictCheck, objStack, srcStack) {
    const hasCustomizer = typeof customizer === 'function';
    if (isDeepComparable(object, source)) {
        // 假设循环结构是相等的。
        objStack = objStack || [];
        srcStack = srcStack || [];
        let stackLen = objStack.length;
        while (stackLen--) {
            // 遍历对象的堆栈,如果存在循环依赖,立即进行比较。
            // 相等才退出,否则必须匹配。
            if (objStack[stackLen] === object && srcStack[stackLen] === source) {
                return true;
            }
        }
        // 将对象添加到遍历对象的堆栈中。
        objStack.push(object);
        srcStack.push(source);
        const keys = allKeys(source);
        let length = keys.length;
        while (length--) {
            const key = keys[length];
            if (!(key in object)) {
                return false;
            }
            if (hasCustomizer) {
                const compared = customizer(object[key], source[key], key, object, source, objStack, srcStack);
                if (compared !== nativeUndefined) {
                    if (!compared) {
                        return false;
                    }
                    continue;
                }
            }
            // 循环对象
            if (!baseIsMatch(object[key], source[key], customizer, strictCheck, objStack, srcStack)) {
                return false;
            }
        }
        // 从遍历对象的堆栈中删除
        objStack.pop();
        srcStack.pop();
        return true;
    }
    // 非对象比较
    const result = isEqualDeep(object, source, (objValue, srcValue, k, obj, src) => {
        if (hasCustomizer) {
            const compared = customizer(objValue, srcValue, k, obj, src, objStack, srcStack);
            if (compared !== nativeUndefined) {
                return compared;
            }
        }
        if (isDeepComparable(objValue, srcValue)) {
            return baseIsMatch(objValue, srcValue, customizer, strictCheck, objStack, srcStack);
        }
    }, strictCheck, objStack, srcStack);
    return result;
}
/**
 * 执行一个深比较,确定 `object` 是否含有和 `source` 完全相等的属性值。
 *
 * 注意:只有普通对象才会执行部分匹配,函数、数组不会执行部分匹配。
 *
 * 如果 `strictCheck=true`, 以下值不相等:
 *
 * 1. `0` `-0`
 * 2. `typeof` 不同类型,如 `1` `Object(1)`
 * 3. 无效日期对象,如 `new Date('')` `new Date('abc')`
 *
 * @alias module:Language.isMatch
 * @since 1.4.0
 * @requires module:Language.isEqual
 * @param {Object} object 要检查的对象。
 * @param {Object} source 属性值相匹配的对象。
 * @param {Function} [customizer] 自定义比较。
 * @param {boolean} [strictCheck=false] 严格比较。默认 `false`。
 * @returns {boolean} 如果 `object` 匹配,返回 `true`,否则返回 `false`。
 * @example
 *
 * const object = { a: 1, b: -0 }
 *
 * isMatch(object, { a: 1 }); // true
 * isMatch(object, { b: 0 }); // true
 *
 * // 严格比较
 * isMatch(object, { b: 0 }, undefined, true); // false
 *
 * // 自定义比较
 * function customizer(objValue, srcValue){
 *   if(typeof objValue === 'string' && typeof srcValue === 'string'){
 *     return true;
 *   }
 * }
 * isMatch({ foo: 'a' }, { foo: 'b' }, customizer); // true
 * isMatch({ foo: ['a'] }, { foo: ['b'] }, customizer); // true
 * isMatch({ foo: 'a' }, { foo: 'b' }, customizer); // true
 *
 */
function isMatch(object, source, customizer, strictCheck = false) {
    if (typeof customizer === 'function') {
        const compared = customizer(object, source);
        if (compared !== nativeUndefined) {
            return !!compared;
        }
    }
    return baseIsMatch(object, source, customizer, strictCheck, nativeUndefined, nativeUndefined);
}
export default isMatch;