【源码阅读 | xe-utils源码 | 07】isMatch 判断属性中的键值是否包含在对象中

1. 背景

现有两个对象或值,需要实现如下代码效果(本文均以第一个参数称为A参数第二个参数称为B参数,下文同)

  • 若 B 对象中的键都存在于 obj 中,且值能一一对应,则返回 true(见下代码第一行)
  • 若 B 对象中有一个键不存在于 obj 中,则返回 false(见下代码第二行)
console.log(isMatch({ aa: 11, bb: 22 }, { bb: 22 })) // true -> bb 存在且值能对应,返回 true
console.log(isMatch({ bb: 22 }, { aa: 11, bb: 22 })) // false -> aa 不存在于第一个参数中,返回 false
console.log(isMatch({ aa: 11, bb: 22 }, { bb: 33 })) // false -> bb 存在于第一个参数中,但值不对应,返回 false

console.log(isMatch([1], { 0: 1 })) // true

2. 源码解析

实现的过程注意点如下:

  • 一旦A参数中存在,但B参数中不存在的键,则直接返回 false
  • 数组也有键值对,需考虑数组与对象比较的情况

  源码中会有一些我们未讲过的函数的封装,如果你觉得过于复杂,可以直接阅读 2.2 中笔者以相同思路 简化过的代码,其中包含每个步骤的详细注释,可学习到的思路基本一致。

2.1 xe-utils 源码实现 isMatch

var keys = require("./keys");
var findIndexOf = require("./findIndexOf");
var isEqual = require("./isEqual");

var some = require("./some");
var includeArrays = require("./includeArrays");

/**
 * 判断属性中的键和值是否包含在对象中
 *
 * @param {Object/Array} obj 对象
 * @param {Object} source 值
 * @return {Boolean}
 */
function isMatch(obj, source) {
  var objKeys = keys(obj);
  var sourceKeys = keys(source);
  if (sourceKeys.length) {
    if (includeArrays(objKeys, sourceKeys)) {
      return some(sourceKeys, function (key2) {
        return (
          findIndexOf(objKeys, function (key1) {
            return key1 === key2 && isEqual(obj[key1], source[key2]);
          }) > -1
        );
      });
    }
  } else {
    return true;
  }
  return isEqual(obj, source);
}

module.exports = isMatch;

2.2 简化代码

注意:

var isEqual = require('./isEqual')
var includeArrays = require('../Array/includeArrays')

// obj 为较大的集合,source 为被比对的子集
function isMatch(obj, source) {
  // 1.获取对象的 key
  const k1 = Object.keys(obj)
  const k2 = Object.keys(source)

  // 2.若source无值,则直接返回true
  if (!k2.length) return true

  // 3.若待匹配项中存在key值与被匹配项对应,则说明键对应得上(说明k1包含k2)
  if (includeArrays(k1, k2)) {
    return k2.some((key) => {
      // 4.匹配键值,只要有一个键值对应得上,则返回true
      return isEqual(obj[key], source[key])
    })
  }

  // 5.除对象和数组之外的特殊情况判断
  return isEqual(obj, source)
}

module.exports = isMatch

2.3 includeArrays

注意点如下:

  • includes:本文不讨论该函数源码,可以理解为是对 Array.includes 的封装,内加了一些对兼容性的判断
  • isArray:该函数的源码在前面文章已讲解,还未读过的同学请务必前往复习一下 【源码阅读 | xe-utils源码 | 02】判断Array类型
  • 需要判断传入的参数 是否为数组避免 非 Array 型使用 Array.includes 方法会 报错

实现思路非常简单:
  遍历两个数组元素,一旦 keyA 数组中不包含 keyB 的任一 key 值,直接返回 false;否则返回 true。

  举例:keyA = [1, 2, 3] keyB = [2, 3, 4],4就是 keyA 中不存在的 key,因此返回 false

includeArrays.js 源码实现

var isArray = require("./isArray");
var includes = require("./includes");

/**
 * 判断数组是否包含另一数组
 *
 * @param {Array} array1 数组
 * @param {Array} array2 被包含数组
 * @return {Boolean}
 */
function includeArrays(array1, array2) {
  var len;
  var index = 0;
  if (isArray(array1) && isArray(array2)) {
    for (len = array2.length; index < len; index++) {
      if (!includes(array1, array2[index])) {
        return false;
      }
    }
    return true;
  }
  return includes(array1, array2);
}

module.exports = includeArrays;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值