# 判断两个对象是否相等

# 简易版本: 判断两个字面量对象的值是否相等,而且只判断第一层

function objectShallowEqual(objA, objB, fields) {
  if (!objA || !objB) {
    return false;
  }
  let fieldsA = [];
  let fieldsB = [];
  if (!fields) {
    fieldsA = Object.keys(objA);
    fieldsB = Object.keys(objB);
    fields = fieldsA;
  } else {
  }
  if (fieldsA.length !== fieldsB.length) {
    return false;
  }
  let flag = true;
  for (let key of fields) {
    if (objA[key] !== objB[key]) {
      flag = false;
      break;
    }
  }

  return flag;
}

# 全功能版本

/* 
NaN 和 NaN 是相等
[1] 和 [1] 是相等
{value: 1} 和 {value: 1} 是相等
不仅仅是这些长得一样的,还有

1 和 new Number(1) 是相等
'Curly' 和 new String('Curly') 是相等
true 和 new Boolean(true) 是相等
*/

var _toString = Object.prototype.toString;

function isFunction(obj) {
  return _toString.call(obj) === '[object Function]';
}

function eq(a, b, aStack, bStack) {
  // === 结果为 true 的区别出 +0 和 -0
  if (a === b) return a !== 0 || 1 / a === 1 / b;

  // typeof null 的结果为 object ,这里做判断,是为了让有 null 的情况尽早退出函数
  if (a == null || b == null) return false;

  // 判断 NaN
  if (a !== a) return b !== b;

  // 判断参数 a 类型,如果是基本类型,在这里可以直接返回 false
  var type = typeof a;
  if (type !== 'function' && type !== 'object' && typeof b != 'object') return false;

  // 更复杂的对象使用 deepEq 函数进行深度比较
  return deepEq(a, b, aStack, bStack);
}

function deepEq(a, b, aStack, bStack) {
  // a 和 b 的内部属性 [[class]] 相同时 返回 true
  var className = _toString.call(a);
  if (className !== _toString.call(b)) return false;

  switch (className) {
    case '[object RegExp]':
    case '[object String]':
      return '' + a === '' + b;
    case '[object Number]':
      if (+a !== +a) return +b !== +b;
      return +a === 0 ? 1 / +a === 1 / b : +a === +b;
    case '[object Date]':
    case '[object Boolean]':
      return +a === +b;
  }

  var areArrays = className === '[object Array]';
  // 不是数组
  if (!areArrays) {
    // 过滤掉两个函数的情况
    if (typeof a != 'object' || typeof b != 'object') return false;

    var aCtor = a.constructor,
      bCtor = b.constructor;
    // aCtor 和 bCtor 必须都存在并且都不是 Object 构造函数的情况下,aCtor 不等于 bCtor, 那这两个对象就真的不相等啦
    if (
      aCtor !== bCtor &&
      !(
        isFunction(aCtor) &&
        aCtor instanceof aCtor &&
        isFunction(bCtor) &&
        bCtor instanceof bCtor
      ) &&
      'constructor' in a &&
      'constructor' in b
    ) {
      return false;
    }
  }

  aStack = aStack || [];
  bStack = bStack || [];
  var length = aStack.length;

  // 检查是否有循环引用的部分
  while (length--) {
    if (aStack[length] === a) {
      return bStack[length] === b;
    }
  }

  aStack.push(a);
  bStack.push(b);

  // 数组判断
  if (areArrays) {
    length = a.length;
    if (length !== b.length) return false;

    while (length--) {
      if (!eq(a[length], b[length], aStack, bStack)) return false;
    }
  }
  // 对象判断
  else {
    var keys = Object.keys(a),
      key;
    length = keys.length;

    if (Object.keys(b).length !== length) return false;
    while (length--) {
      key = keys[length];
      if (!(b.hasOwnProperty(key) && eq(a[key], b[key], aStack, bStack))) return false;
    }
  }

  aStack.pop();
  bStack.pop();
  return true;
}

export default eq;

上次更新: 6/10/2026, 9:33:30 AM