underscore.js 内部方法 eq(a,b,aStack,bStack)
 // Internal recursive comparison function for `isEqual`.
  var eq = function(a, b, aStack, bStack) {
    // Identical objects are equal. `0 === -0`, but they aren't identical.
    // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
    if (a === b) return a !== 0 || 1 / a === 1 / b;
    // A strict comparison is necessary because `null == undefined`.
    if (a == null || b == null) return a === b;
    // Unwrap any wrapped objects.
    if (a instanceof _) a = a._wrapped;
    if (b instanceof _) b = b._wrapped;
    // Compare `[[Class]]` names.
    var className = toString.call(a);
    if (className !== toString.call(b)) return false;
    switch (className) {
      // Strings, numbers, regular expressions, dates, and booleans are compared by value.
      case '[object RegExp]':
      // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
      case '[object String]':
        // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
        // equivalent to `new String("5")`.
        return '' + a === '' + b;
      case '[object Number]':
        // `NaN`s are equivalent, but non-reflexive.
        // Object(NaN) is equivalent to NaN
        if (+a !== +a) return +b !== +b;
        // An `egal` comparison is performed for other numeric values.
        return +a === 0 ? 1 / +a === 1 / b : +a === +b;
      case '[object Date]':
      case '[object Boolean]':
        // Coerce dates and booleans to numeric primitive values. Dates are compared by their
        // millisecond representations. Note that invalid dates with millisecond representations
        // of `NaN` are not equivalent.
        return +a === +b;
    }

    var areArrays = className === '[object Array]';
    if (!areArrays) {
      if (typeof a != 'object' || typeof b != 'object') return false;

      // Objects with different constructors are not equivalent, but `Object`s or `Array`s
      // from different frames are.
      var aCtor = a.constructor, bCtor = b.constructor;
      if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
                               _.isFunction(bCtor) && bCtor instanceof bCtor)
                          && ('constructor' in a && 'constructor' in b)) {
        return false;
      }
    }
    // Assume equality for cyclic structures. The algorithm for detecting cyclic
    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
    var length = aStack.length;
    while (length--) {
      // Linear search. Performance is inversely proportional to the number of
      // unique nested structures.
      if (aStack[length] === a) return bStack[length] === b;
    }

    // Add the first object to the stack of traversed objects.
    aStack.push(a);
    bStack.push(b);
    var size, result;
    // Recursively compare objects and arrays.
    if (areArrays) {
      // Compare array lengths to determine if a deep comparison is necessary.
      size = a.length;
      result = size === b.length;
      if (result) {
        // Deep compare the contents, ignoring non-numeric properties.
        while (size--) {
          if (!(result = eq(a[size], b[size], aStack, bStack))) break;
        }
      }
    } else {
      // Deep compare objects.
      var keys = _.keys(a), key;
      size = keys.length;
      // Ensure that both objects contain the same number of properties before comparing deep equality.
      result = _.keys(b).length === size;
      if (result) {
        while (size--) {
          // Deep compare each member
          key = keys[size];
          if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
        }
      }
    }
    // Remove the first object from the stack of traversed objects.
    aStack.pop();
    bStack.pop();
    return result;
  };

  // Perform a deep comparison to check if two objects are equal.
  _.isEqual = function(a, b) {
    return eq(a, b, [], []);
  };

// Assume equality for cyclic structures. The algorithm for detecting cyclic
// structures is adapted from ES 5.1 section 15.12.3, abstract operation JO.
var length = aStack.length;
while (length--) {
// Linear search. Performance is inversely proportional to the number of
// unique nested structures.
if (aStack[length] === a) return bStack[length] === b;
}
这几段代码在什么情况下会进入if条件语句 请教高人给个例子 ,谢谢!

2个回答

终于看明白了,原来是解决循环引用对象的问题

var obj1={
                    t1:"ying",
                };
        obj1["test1"]=obj1;
        var obj2={
                    t1:"ying",
                };
        obj2["test1"]=obj2;
        alert(_.isEqual(obj1,obj2));

这个列子会进入那个if条件语句,并且返回true!

目测是遍历aStack数组(从最后开始遍历),碰到和a类型并且内容都一样的就会执行。

如eq('1', '2', ['1', '2', '3'], ['1', '2', '3'])会执行并且返回true

eq(1, 2, ['1', '2', '3'], ['1', '2', '3'])这个不会,因为类型不匹配。

yingjianglin
yingjianglin 回复showbo: 我还是贴一下整个代码吧,我都看了好久了,就是不明白上面那段
5 年多之前 回复
showbo
支付宝加好友偷能量挖,胡杨等着我的招呼 回复yingjianglin: 我的代码是正对你贴出来的,如果还有if (a === b)这种判断,就直接这个if语句了
5 年多之前 回复
yingjianglin
yingjianglin 回复showbo: 你给的这个 eq('1', '1', ['1', '2', '3'], ['1', '2', '3']) 例子,不会进入上面的循环,在进入eq函数的,第一条语句就返回了,代码如下if (a === b) return a !== 0 || 1 / a === 1 / b; 这一句 返回true 整个eq函数就结束了
5 年多之前 回复
showbo
支付宝加好友偷能量挖,胡杨等着我的招呼 回复yingjianglin: 扩展的是数组的方法吧。。应该是比较2个数组是否完全一样,包括类型===3个等是连类型一起比较的,==2个等不比较类型,如1=='1'为true,1==='1'为false,因为类型不同
5 年多之前 回复
yingjianglin
yingjianglin 谢谢你的回答,这个eq函数内部调用才会传递4个参数 ,外部调用的话是通过_.isEqual(a,b) 只需传入需要比对的a,b对象,aStack,bStack在内部函数中存放的是a,b对象中存放的可循环比对对象,通过递归迭代的方式进行深层比较,整个eq内部函数基本都能看懂,就是上面那几段,不知道到底什么意思,或者说什么样的例子才能进入上面代码的if条件语句
5 年多之前 回复
showbo
支付宝加好友偷能量挖,胡杨等着我的招呼 eq('1', '2', ['1', '2', '3'], ['1', '2', '3'])会执行并且返回false,这个搞错。eq('1', '1', ['1', '2', '3'], ['1', '2', '3'])才是true
5 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐