Remove a and b use from baseIsEqual.

This commit is contained in:
John-David Dalton
2014-03-23 14:11:54 -07:00
parent 1d02c288b3
commit de70ef1ef6
2 changed files with 107 additions and 100 deletions

View File

@@ -777,61 +777,61 @@
* @param {Array} [stackB=[]] Tracks traversed `other` objects. * @param {Array} [stackB=[]] Tracks traversed `other` objects.
* @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
*/ */
function baseIsEqual(a, b, stackA, stackB) { function baseIsEqual(value, other, stackA, stackB) {
if (a === b) { if (value === other) {
return a !== 0 || (1 / a == 1 / b); return value !== 0 || (1 / value == 1 / other);
} }
var type = typeof a, var valType = typeof value,
otherType = typeof b; othType = typeof other;
if (a === a && (a == null || b == null || if (value === value && (value == null || other == null ||
(type != 'function' && type != 'object' && otherType != 'function' && otherType != 'object'))) { (valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object'))) {
return false; return false;
} }
var className = toString.call(a), var valClass = toString.call(value),
otherClass = toString.call(b); othClass = toString.call(other);
if (className != otherClass) { if (valClass != othClass) {
return false; return false;
} }
switch (className) { switch (valClass) {
case boolClass: case boolClass:
case dateClass: case dateClass:
return +a == +b; return +value == +other;
case numberClass: case numberClass:
return a != +a return value != +value
? b != +b ? other != +other
: (a == 0 ? (1 / a == 1 / b) : a == +b); : (value == 0 ? (1 / value == 1 / other) : value == +other);
case regexpClass: case regexpClass:
case stringClass: case stringClass:
return a == String(b); return value == String(other);
} }
var isArr = className == arrayClass; var isArr = valClass == arrayClass;
if (!isArr) { if (!isArr) {
var aWrapped = a instanceof lodash, var valWrapped = value instanceof lodash,
bWrapped = b instanceof lodash; othWrapped = other instanceof lodash;
if (aWrapped || bWrapped) { if (valWrapped || othWrapped) {
return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, stackA, stackB); return baseIsEqual(valWrapped ? value.__wrapped__ : value, othWrapped ? other.__wrapped__ : other, stackA, stackB);
} }
if (className != objectClass) { if (valClass != objectClass) {
return false; return false;
} }
var ownCtorA = hasOwnProperty.call(a, 'constructor'), var hasValCtor = hasOwnProperty.call(value, 'constructor'),
ownCtorB = hasOwnProperty.call(b, 'constructor'); hasOthCtor = hasOwnProperty.call(other, 'constructor');
if (ownCtorA !== ownCtorB) { if (hasValCtor !== hasOthCtor) {
return false; return false;
} }
if (!ownCtorA) { if (!hasValCtor) {
var ctorA = a.constructor, var valCtor = value.constructor,
ctorB = b.constructor; othCtor = other.constructor;
if (ctorA != ctorB && if (valCtor != othCtor &&
!(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) && !(isFunction(valCtor) && valCtor instanceof valCtor && isFunction(othCtor) && othCtor instanceof othCtor) &&
('constructor' in a && 'constructor' in b) ('constructor' in value && 'constructor' in other)
) { ) {
return false; return false;
} }
@@ -842,39 +842,39 @@
var length = stackA.length; var length = stackA.length;
while (length--) { while (length--) {
if (stackA[length] == a) { if (stackA[length] == value) {
return stackB[length] == b; return stackB[length] == other;
} }
} }
var result = true, var result = true,
size = 0; size = 0;
stackA.push(a); stackA.push(value);
stackB.push(b); stackB.push(other);
if (isArr) { if (isArr) {
size = b.length; size = other.length;
result = size == a.length; result = size == value.length;
if (result) { if (result) {
while (size--) { while (size--) {
if (!(result = baseIsEqual(a[size], b[size], stackA, stackB))) { if (!(result = baseIsEqual(value[size], other[size], stackA, stackB))) {
break; break;
} }
} }
} }
} }
else { else {
baseForIn(b, function(value, key, b) { baseForIn(other, function(othValue, key, other) {
if (hasOwnProperty.call(b, key)) { if (hasOwnProperty.call(other, key)) {
size++; size++;
return !(result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, stackA, stackB)) && breakIndicator; return !(result = hasOwnProperty.call(value, key) && baseIsEqual(value[key], othValue, stackA, stackB)) && breakIndicator;
} }
}); });
if (result) { if (result) {
baseForIn(a, function(value, key, a) { baseForIn(value, function(valValue, key, value) {
if (hasOwnProperty.call(a, key)) { if (hasOwnProperty.call(value, key)) {
return !(result = --size > -1) && breakIndicator; return !(result = --size > -1) && breakIndicator;
} }
}); });

121
lodash.js
View File

@@ -1135,8 +1135,8 @@
stackB.push(result); stackB.push(result);
// recursively populate clone (susceptible to call stack limits) // recursively populate clone (susceptible to call stack limits)
(isArr ? baseEach : baseForOwn)(value, function(objValue, key) { (isArr ? baseEach : baseForOwn)(value, function(valValue, key) {
result[key] = baseClone(objValue, isDeep, callback, stackA, stackB); result[key] = baseClone(valValue, isDeep, callback, stackA, stackB);
}); });
return result; return result;
@@ -1557,84 +1557,91 @@
* @param {Array} [stackB=[]] Tracks traversed `other` objects. * @param {Array} [stackB=[]] Tracks traversed `other` objects.
* @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
*/ */
function baseIsEqual(a, b, callback, isWhere, stackA, stackB) { function baseIsEqual(value, other, callback, isWhere, stackA, stackB) {
if (callback) { if (callback) {
var result = callback(a, b); var result = callback(value, other);
if (typeof result != 'undefined') { if (typeof result != 'undefined') {
return !!result; return !!result;
} }
} }
// exit early for identical values // exit early for identical values
if (a === b) { if (value === other) {
// treat `+0` vs. `-0` as not equal // treat `+0` vs. `-0` as not equal
return a !== 0 || (1 / a == 1 / b); return value !== 0 || (1 / value == 1 / other);
} }
var type = typeof a, var valType = typeof value,
otherType = typeof b; othType = typeof other;
// exit early for unlike primitive values // exit early for unlike primitive values
if (a === a && (a == null || b == null || if (value === value && (value == null || other == null ||
(type != 'function' && type != 'object' && otherType != 'function' && otherType != 'object'))) { (valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object'))) {
return false; return false;
} }
// compare [[Class]] names // compare [[Class]] names
var className = toString.call(a), var valClass = toString.call(value),
otherClass = toString.call(b); othClass = toString.call(other);
if (className == argsClass) { if (valClass == argsClass) {
className = objectClass; valClass = objectClass;
} }
if (otherClass == argsClass) { if (othClass == argsClass) {
otherClass = objectClass; othClass = objectClass;
} }
if (className != otherClass) { if (valClass != othClass) {
return false; return false;
} }
switch (className) { switch (valClass) {
case boolClass: case boolClass:
case dateClass: case dateClass:
// coerce dates and booleans to numbers, dates to milliseconds and booleans // coerce dates and booleans to numbers, dates to milliseconds and booleans
// to `1` or `0` treating invalid dates coerced to `NaN` as not equal // to `1` or `0` treating invalid dates coerced to `NaN` as not equal
return +a == +b; return +value == +other;
case numberClass: case numberClass:
// treat `NaN` vs. `NaN` as equal // treat `NaN` vs. `NaN` as equal
return (a != +a) return (value != +value)
? b != +b ? other != +other
// but treat `-0` vs. `+0` as not equal // but treat `-0` vs. `+0` as not equal
: (a == 0 ? (1 / a == 1 / b) : a == +b); : (value == 0 ? (1 / value == 1 / other) : value == +other);
case regexpClass: case regexpClass:
case stringClass: case stringClass:
// coerce regexes to strings (http://es5.github.io/#x15.10.6.4) // coerce regexes to strings (http://es5.github.io/#x15.10.6.4)
// treat string primitives and their corresponding object instances as equal // treat string primitives and their corresponding object instances as equal
return a == String(b); return value == String(other);
} }
var isArr = className == arrayClass; var isArr = valClass == arrayClass;
if (!isArr) { if (!isArr) {
// unwrap any `lodash` wrapped values // unwrap any `lodash` wrapped values
var aWrapped = hasOwnProperty.call(a, '__wrapped__'), var valWrapped = hasOwnProperty.call(value, '__wrapped__'),
bWrapped = hasOwnProperty.call(b, '__wrapped__'); othWrapped = hasOwnProperty.call(other, '__wrapped__');
if (aWrapped || bWrapped) { if (valWrapped || othWrapped) {
return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB); return baseIsEqual(valWrapped ? value.__wrapped__ : value, othWrapped ? other.__wrapped__ : other, callback, isWhere, stackA, stackB);
} }
// exit for functions and DOM nodes // exit for functions and DOM nodes
if (className != objectClass || (!support.nodeClass && (isNode(a) || isNode(b)))) { if (valClass != objectClass || (!support.nodeClass && (isNode(value) || isNode(other)))) {
return false; return false;
} }
// in older versions of Opera, `arguments` objects have `Array` constructors var hasValCtor = hasOwnProperty.call(value, 'constructor'),
var ctorA = !support.argsObject && isArguments(a) ? Object : a.constructor, hasOthCtor = hasOwnProperty.call(other, 'constructor');
ctorB = !support.argsObject && isArguments(b) ? Object : b.constructor;
// non `Object` object instances with different constructors are not equal if (hasValCtor !== hasOthCtor) {
if (ctorA != ctorB &&
!(hasOwnProperty.call(a, 'constructor') && hasOwnProperty.call(b, 'constructor')) &&
!(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) &&
('constructor' in a && 'constructor' in b)
) {
return false; return false;
} }
if (!hasValCtor) {
// in older versions of Opera, `arguments` objects have `Array` constructors
var valCtor = !support.argsObject && isArguments(value) ? Object : value.constructor,
othCtor = !support.argsObject && isArguments(other) ? Object : other.constructor;
// non `Object` object instances with different constructors are not equal
if (valCtor != othCtor &&
!(isFunction(valCtor) && valCtor instanceof valCtor && isFunction(othCtor) && othCtor instanceof othCtor) &&
('constructor' in value && 'constructor' in other)
) {
return false;
}
}
} }
// assume cyclic structures are equal // assume cyclic structures are equal
// the algorithm for detecting cyclic structures is adapted from ES 5.1 // the algorithm for detecting cyclic structures is adapted from ES 5.1
@@ -1645,37 +1652,37 @@
var length = stackA.length; var length = stackA.length;
while (length--) { while (length--) {
if (stackA[length] == a) { if (stackA[length] == value) {
return stackB[length] == b; return stackB[length] == other;
} }
} }
var size = 0; var size = 0;
result = true; result = true;
// add `a` and `b` to the stack of traversed objects // add `value` and `other` to the stack of traversed objects
stackA.push(a); stackA.push(value);
stackB.push(b); stackB.push(other);
// recursively compare objects and arrays (susceptible to call stack limits) // recursively compare objects and arrays (susceptible to call stack limits)
if (isArr) { if (isArr) {
// compare lengths to determine if a deep comparison is necessary // compare lengths to determine if a deep comparison is necessary
length = a.length; length = value.length;
size = b.length; size = other.length;
result = size == length; result = size == length;
if (result || isWhere) { if (result || isWhere) {
// deep compare the contents, ignoring non-numeric properties // deep compare the contents, ignoring non-numeric properties
while (size--) { while (size--) {
var index = length, var index = length,
value = b[size]; othValue = other[size];
if (isWhere) { if (isWhere) {
while (index--) { while (index--) {
if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) { if ((result = baseIsEqual(value[index], othValue, callback, isWhere, stackA, stackB))) {
break; break;
} }
} }
} else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) { } else if (!(result = baseIsEqual(value[size], othValue, callback, isWhere, stackA, stackB))) {
break; break;
} }
} }
@@ -1684,20 +1691,20 @@
else { else {
// deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys` // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
// which, in this case, is more costly // which, in this case, is more costly
baseForIn(b, function(value, key, b) { baseForIn(other, function(othValue, key, other) {
if (hasOwnProperty.call(b, key)) { if (hasOwnProperty.call(other, key)) {
// count the number of properties. // count the number of properties.
size++; size++;
// deep compare each property value. // deep compare each property value.
return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB)); return (result = hasOwnProperty.call(value, key) && baseIsEqual(value[key], othValue, callback, isWhere, stackA, stackB));
} }
}); });
if (result && !isWhere) { if (result && !isWhere) {
// ensure both objects have the same number of properties // ensure both objects have the same number of properties
baseForIn(a, function(value, key, a) { baseForIn(value, function(valValue, key, value) {
if (hasOwnProperty.call(a, key)) { if (hasOwnProperty.call(value, key)) {
// `size` will be `-1` if `a` has more properties than `b` // `size` will be `-1` if `value` has more properties than `other`
return (result = --size > -1); return (result = --size > -1);
} }
}); });
@@ -6184,12 +6191,12 @@
// treat `-0` vs. `+0` as not equal // treat `-0` vs. `+0` as not equal
return value !== 0 || (1 / value == 1 / other); return value !== 0 || (1 / value == 1 / other);
} }
var vType = typeof value, var valType = typeof value,
oType = typeof other; othType = typeof other;
// exit early for unlike primitive values // exit early for unlike primitive values
if (value === value && (value == null || other == null || if (value === value && (value == null || other == null ||
(vType != 'function' && vType != 'object' && oType != 'function' && oType != 'object'))) { (valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object'))) {
return false; return false;
} }
} }