joint.all.js
function baseIsEqual(a, b, callback, isWhere, stackA, stackB) {
      // used to indicate that when comparing objects, `a` has at least the properties of `b`
      if (callback) {
        var result = callback(a, b);
        if (typeof result != 'undefined') {
          return !!result;
        }
      }
      // exit early for identical values
      if (a === b) {
        // treat `+0` vs. `-0` as not equal
        return a !== 0 || (1 / a == 1 / b);
      }
      var type = typeof a,
          otherType = typeof b;

      // exit early for unlike primitive values
      if (a === a &&
          !(a && objectTypes[type]) &&
          !(b && objectTypes[otherType])) {
        return false;
      }
      // exit early for `null` and `undefined` avoiding ES3's Function#call behavior
      // http://es5.github.io/#x15.3.4.4
      if (a == null || b == null) {
        return a === b;
      }
      // compare [[Class]] names
      var className = toString.call(a),
          otherClass = toString.call(b);

      if (className == argsClass) {
        className = objectClass;
      }
      if (otherClass == argsClass) {
        otherClass = objectClass;
      }
      if (className != otherClass) {
        return false;
      }
      switch (className) {
        case boolClass:
        case dateClass:
          // coerce dates and booleans to numbers, dates to milliseconds and booleans
          // to `1` or `0` treating invalid dates coerced to `NaN` as not equal
          return +a == +b;

        case numberClass:
          // treat `NaN` vs. `NaN` as equal
          return (a != +a)
            ? b != +b
            // but treat `+0` vs. `-0` as not equal
            : (a == 0 ? (1 / a == 1 / b) : a == +b);

        case regexpClass:
        case stringClass:
          // coerce regexes to strings (http://es5.github.io/#x15.10.6.4)
          // treat string primitives and their corresponding object instances as equal
          return a == String(b);
      }
      var isArr = className == arrayClass;
      if (!isArr) {
        // unwrap any `lodash` wrapped values
        if (hasOwnProperty.call(a, '__wrapped__ ') || hasOwnProperty.call(b, '__wrapped__')) {
          return baseIsEqual(a.__wrapped__ || a, b.__wrapped__ || b, callback, isWhere, stackA, stackB);
        }
        // exit for functions and DOM nodes
        if (className != objectClass) {
          return false;
        }
        // in older versions of Opera, `arguments` objects have `Array` constructors
        var ctorA = a.constructor,
            ctorB = b.constructor;

        // non `Object` object instances with different constructors are not equal
        if (ctorA != ctorB && !(
              isFunction(ctorA) && ctorA instanceof ctorA &&
              isFunction(ctorB) && ctorB instanceof ctorB
            )) {
          return false;
        }
      }
      // assume cyclic structures are equal
      // the algorithm for detecting cyclic structures is adapted from ES 5.1
      // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3)
      var initedStack = !stackA;
      stackA || (stackA = getArray());
      stackB || (stackB = getArray());

      var length = stackA.length;
      while (length--) {
        if (stackA[length] == a) {
          return stackB[length] == b;
        }
      }
      var size = 0;
      result = true;

      // add `a` and `b` to the stack of traversed objects
      stackA.push(a);
      stackB.push(b);

      // recursively compare objects and arrays (susceptible to call stack limits)
      if (isArr) {
        length = a.length;
        size = b.length;

        // compare lengths to determine if a deep comparison is necessary
        result = size == a.length;
        if (!result && !isWhere) {
          return result;
        }
        // deep compare the contents, ignoring non-numeric properties
        while (size--) {
          var index = length,
              value = b[size];

          if (isWhere) {
            while (index--) {
              if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) {
                break;
              }
            }
          } else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) {
            break;
          }
        }
        return result;
      }
      // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
      // which, in this case, is more costly
      forIn(b, function(value, key, b) {
        if (hasOwnProperty.call(b, key)) {
          // count the number of properties.
          size++;
          // deep compare each property value.
          return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB));
        }
      });

      if (result && !isWhere) {
        // ensure both objects have the same number of properties
        forIn(a, function(value, key, a) {
          if (hasOwnProperty.call(a, key)) {
            // `size` will be `-1` if `a` has more properties than `b`
            return (result = --size > -1);
          }
        });
      }
      if (initedStack) {
        releaseArray(stackA);
        releaseArray(stackB);
      }
      return result;
    }
function baseIsEqual(a, b, callback, isWhere, stackA, stackB) {
      // used to indicate that when comparing objects, `a` has at least the properties of `b`
      if (callback) {
        var result = callback(a, b);
        if (typeof result != 'undefined') {
          return !!result;
        }
      }
      // exit early for identical values
      if (a === b) {
        // treat `+0` vs. `-0` as not equal
        return a !== 0 || (1 / a == 1 / b);
      }
      var type = typeof a,
          otherType = typeof b;

      // exit early for unlike primitive values
      if (a === a &&
          !(a && objectTypes[type]) &&
          !(b && objectTypes[otherType])) {
        return false;
      }
      // exit early for `null` and `undefined` avoiding ES3's Function#call behavior
      // http://es5.github.io/#x15.3.4.4
      if (a == null || b == null) {
        return a === b;
      }
      // compare [[Class]] names
      var className = toString.call(a),
          otherClass = toString.call(b);

      if (className == argsClass) {
        className = objectClass;
      }
      if (otherClass == argsClass) {
        otherClass = objectClass;
      }
      if (className != otherClass) {
        return false;
      }
      switch (className) {
        case boolClass:
        case dateClass:
          // coerce dates and booleans to numbers, dates to milliseconds and booleans
          // to `1` or `0` treating invalid dates coerced to `NaN` as not equal
          return +a == +b;

        case numberClass:
          // treat `NaN` vs. `NaN` as equal
          return (a != +a)
            ? b != +b
            // but treat `+0` vs. `-0` as not equal
            : (a == 0 ? (1 / a == 1 / b) : a == +b);

        case regexpClass:
        case stringClass:
          // coerce regexes to strings (http://es5.github.io/#x15.10.6.4)
          // treat string primitives and their corresponding object instances as equal
          return a == String(b);
      }
      var isArr = className == arrayClass;
      if (!isArr) {
        // unwrap any `lodash` wrapped values
        if (hasOwnProperty.call(a, '__wrapped__ ') || hasOwnProperty.call(b, '__wrapped__')) {
          return baseIsEqual(a.__wrapped__ || a, b.__wrapped__ || b, callback, isWhere, stackA, stackB);
        }
        // exit for functions and DOM nodes
        if (className != objectClass) {
          return false;
        }
        // in older versions of Opera, `arguments` objects have `Array` constructors
        var ctorA = a.constructor,
            ctorB = b.constructor;

        // non `Object` object instances with different constructors are not equal
        if (ctorA != ctorB && !(
              isFunction(ctorA) && ctorA instanceof ctorA &&
              isFunction(ctorB) && ctorB instanceof ctorB
            )) {
          return false;
        }
      }
      // assume cyclic structures are equal
      // the algorithm for detecting cyclic structures is adapted from ES 5.1
      // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3)
      var initedStack = !stackA;
      stackA || (stackA = getArray());
      stackB || (stackB = getArray());

      var length = stackA.length;
      while (length--) {
        if (stackA[length] == a) {
          return stackB[length] == b;
        }
      }
      var size = 0;
      result = true;

      // add `a` and `b` to the stack of traversed objects
      stackA.push(a);
      stackB.push(b);

      // recursively compare objects and arrays (susceptible to call stack limits)
      if (isArr) {
        length = a.length;
        size = b.length;

        // compare lengths to determine if a deep comparison is necessary
        result = size == a.length;
        if (!result && !isWhere) {
          return result;
        }
        // deep compare the contents, ignoring non-numeric properties
        while (size--) {
          var index = length,
              value = b[size];

          if (isWhere) {
            while (index--) {
              if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) {
                break;
              }
            }
          } else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) {
            break;
          }
        }
        return result;
      }
      // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
      // which, in this case, is more costly
      forIn(b, function(value, key, b) {
        if (hasOwnProperty.call(b, key)) {
          // count the number of properties.
          size++;
          // deep compare each property value.
          return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB));
        }
      });

      if (result && !isWhere) {
        // ensure both objects have the same number of properties
        forIn(a, function(value, key, a) {
          if (hasOwnProperty.call(a, key)) {
            // `size` will be `-1` if `a` has more properties than `b`
            return (result = --size > -1);
          }
        });
      }
      if (initedStack) {
        releaseArray(stackA);
        releaseArray(stackB);
      }
      return result;
    }
function baseIsEqual ( a , b , callback , isWhere , stackA , stackB ) { // used to indicate that when comparing objects, `a` has at least the properties of `b` if ( callback ) { var result = callback ( a , b ) ; if ( typeof result != 'undefined' ) { return ! ! result ; } } // exit early for identical values if ( a === b ) { // treat `+0` vs. `-0` as not equal return a !== 0 || ( 1 / a == 1 / b ) ; } var type = typeof a , otherType = typeof b ; // exit early for unlike primitive values if ( a === a && ! ( a && objectTypes [ type ] ) && ! ( b && objectTypes [ otherType ] ) ) { return false ; } // exit early for `null` and `undefined` avoiding ES3's Function#call behavior // http://es5.github.io/#x15.3.4.4 if ( a == null || b == null ) { return a === b ; } // compare [[Class]] names var className = toString . call ( a ) , otherClass = toString . call ( b ) ; if ( className == argsClass ) { className = objectClass ; } if ( otherClass == argsClass ) { otherClass = objectClass ; } if ( className != otherClass ) { return false ; } switch ( className ) { case boolClass : case dateClass : // coerce dates and booleans to numbers, dates to milliseconds and booleans // to `1` or `0` treating invalid dates coerced to `NaN` as not equal return + a == + b ; case numberClass : // treat `NaN` vs. `NaN` as equal return ( a != + a ) ? b != + b // but treat `+0` vs. `-0` as not equal : ( a == 0 ? ( 1 / a == 1 / b ) : a == + b ) ; case regexpClass : case stringClass : // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) // treat string primitives and their corresponding object instances as equal return a == String ( b ) ; } var isArr = className == arrayClass ; if ( ! isArr ) { // unwrap any `lodash` wrapped values if ( hasOwnProperty . call ( a , '__wrapped__ ' ) || hasOwnProperty . call ( b , '__wrapped__' ) ) { return baseIsEqual ( a . __wrapped__ || a , b . __wrapped__ || b , callback , isWhere , stackA , stackB ) ; } // exit for functions and DOM nodes if ( className != objectClass ) { return false ; } // in older versions of Opera, `arguments` objects have `Array` constructors var ctorA = a . constructor , ctorB = b . constructor ; // non `Object` object instances with different constructors are not equal if ( ctorA != ctorB && ! ( isFunction ( ctorA ) && ctorA instanceof ctorA && isFunction ( ctorB ) && ctorB instanceof ctorB ) ) { return false ; } } // assume cyclic structures are equal // the algorithm for detecting cyclic structures is adapted from ES 5.1 // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3) var initedStack = ! stackA ; stackA || ( stackA = getArray ( ) ) ; stackB || ( stackB = getArray ( ) ) ; var length = stackA . length ; while ( length -- ) { if ( stackA [ length ] == a ) { return stackB [ length ] == b ; } } var size = 0 ; result = true ; // add `a` and `b` to the stack of traversed objects stackA . push ( a ) ; stackB . push ( b ) ; // recursively compare objects and arrays (susceptible to call stack limits) if ( isArr ) { length = a . length ; size = b . length ; // compare lengths to determine if a deep comparison is necessary result = size == a . length ; if ( ! result && ! isWhere ) { return result ; } // deep compare the contents, ignoring non-numeric properties while ( size -- ) { var index = length , value = b [ size ] ; if ( isWhere ) { while ( index -- ) { if ( ( result = baseIsEqual ( a [ index ] , value , callback , isWhere , stackA , stackB ) ) ) { break ; } } } else if ( ! ( result = baseIsEqual ( a [ size ] , value , callback , isWhere , stackA , stackB ) ) ) { break ; } } return result ; } // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys` // which, in this case, is more costly forIn ( b , function ( value , key , b ) { if ( hasOwnProperty . call ( b , key ) ) { // count the number of properties. size ++ ; // deep compare each property value. return ( result = hasOwnProperty . call ( a , key ) && baseIsEqual ( a [ key ] , value , callback , isWhere , stackA , stackB ) ) ; } } ) ; if ( result && ! isWhere ) { // ensure both objects have the same number of properties forIn ( a , function ( value , key , a ) { if ( hasOwnProperty . call ( a , key ) ) { // `size` will be `-1` if `a` has more properties than `b` return ( result = -- size > - 1 ) ; } } ) ; } if ( initedStack ) { releaseArray ( stackA ) ; releaseArray ( stackB ) ; } return result ; }
The base implementation of `_.isEqual`, without support for `thisArg` binding,
that allows partial "_.where" style comparisons.

@private
@param {*} a The value to compare.
@param {*} b The other value to compare.
@param {Function} [callback] The function to customize comparing values.
@param {Function} [isWhere=false] A flag to indicate performing partial comparisons.
@param {Array} [stackA=[]] Tracks traversed `a` objects.
@param {Array} [stackB=[]] Tracks traversed `b` objects.
@returns {boolean} Returns `true` if the values are equivalent, else `false`.
The base implementation of _ . isEqual without support for thisArg binding that allows partial _ . where style comparisons .