mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-10 19:07:49 +00:00
Loosen _.matches to match objects with inherited properties. [closes #1067]
This commit is contained in:
@@ -2265,12 +2265,12 @@
|
|||||||
* @param {*} value The value to compare.
|
* @param {*} value The value to compare.
|
||||||
* @param {*} other The other value to compare.
|
* @param {*} other The other value to compare.
|
||||||
* @param {Function} [customizer] The function to customize comparing values.
|
* @param {Function} [customizer] The function to customize comparing values.
|
||||||
* @param {boolean} [isWhere] Specify performing partial comparisons.
|
* @param {boolean} [isLoose] Specify performing partial comparisons.
|
||||||
* @param {Array} [stackA] Tracks traversed `value` objects.
|
* @param {Array} [stackA] Tracks traversed `value` objects.
|
||||||
* @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(value, other, customizer, isWhere, stackA, stackB) {
|
function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) {
|
||||||
// Exit early for identical values.
|
// Exit early for identical values.
|
||||||
if (value === other) {
|
if (value === other) {
|
||||||
// Treat `+0` vs. `-0` as not equal.
|
// Treat `+0` vs. `-0` as not equal.
|
||||||
@@ -2285,7 +2285,7 @@
|
|||||||
// Return `false` unless both values are `NaN`.
|
// Return `false` unless both values are `NaN`.
|
||||||
return value !== value && other !== other;
|
return value !== value && other !== other;
|
||||||
}
|
}
|
||||||
return baseIsEqualDeep(value, other, baseIsEqual, customizer, isWhere, stackA, stackB);
|
return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2298,12 +2298,12 @@
|
|||||||
* @param {Object} other The other object to compare.
|
* @param {Object} other The other object to compare.
|
||||||
* @param {Function} equalFunc The function to determine equivalents of values.
|
* @param {Function} equalFunc The function to determine equivalents of values.
|
||||||
* @param {Function} [customizer] The function to customize comparing objects.
|
* @param {Function} [customizer] The function to customize comparing objects.
|
||||||
* @param {boolean} [isWhere] Specify performing partial comparisons.
|
* @param {boolean} [isLoose] Specify performing partial comparisons.
|
||||||
* @param {Array} [stackA=[]] Tracks traversed `value` objects.
|
* @param {Array} [stackA=[]] Tracks traversed `value` objects.
|
||||||
* @param {Array} [stackB=[]] Tracks traversed `other` objects.
|
* @param {Array} [stackB=[]] Tracks traversed `other` objects.
|
||||||
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
|
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
|
||||||
*/
|
*/
|
||||||
function baseIsEqualDeep(object, other, equalFunc, customizer, isWhere, stackA, stackB) {
|
function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) {
|
||||||
var objIsArr = isArray(object),
|
var objIsArr = isArray(object),
|
||||||
othIsArr = isArray(other),
|
othIsArr = isArray(other),
|
||||||
objTag = arrayTag,
|
objTag = arrayTag,
|
||||||
@@ -2325,21 +2325,27 @@
|
|||||||
othIsArr = isTypedArray(other);
|
othIsArr = isTypedArray(other);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var objIsObj = objTag == objectTag && !isHostObject(object),
|
var objIsObj = (objTag == objectTag || (isLoose && objTag == funcTag)) && !isHostObject(object),
|
||||||
othIsObj = othTag == objectTag && !isHostObject(other),
|
othIsObj = othTag == objectTag && !isHostObject(other),
|
||||||
isSameTag = objTag == othTag;
|
isSameTag = objTag == othTag;
|
||||||
|
|
||||||
if (isSameTag && !(objIsArr || objIsObj)) {
|
if (isSameTag && !(objIsArr || objIsObj)) {
|
||||||
return equalByTag(object, other, objTag);
|
return equalByTag(object, other, objTag);
|
||||||
}
|
}
|
||||||
var valWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
|
if (isLoose) {
|
||||||
othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
|
if (!isSameTag && !(objIsObj && othIsObj)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var valWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
|
||||||
|
othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
|
||||||
|
|
||||||
if (valWrapped || othWrapped) {
|
if (valWrapped || othWrapped) {
|
||||||
return equalFunc(valWrapped ? object.value() : object, othWrapped ? other.value() : other, customizer, isWhere, stackA, stackB);
|
return equalFunc(valWrapped ? object.value() : object, othWrapped ? other.value() : other, customizer, isLoose, stackA, stackB);
|
||||||
}
|
}
|
||||||
if (!isSameTag) {
|
if (!isSameTag) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Assume cyclic values are equal.
|
// Assume cyclic values are equal.
|
||||||
// For more information on detecting circular references see https://es5.github.io/#JO.
|
// For more information on detecting circular references see https://es5.github.io/#JO.
|
||||||
@@ -2356,7 +2362,7 @@
|
|||||||
stackA.push(object);
|
stackA.push(object);
|
||||||
stackB.push(other);
|
stackB.push(other);
|
||||||
|
|
||||||
var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isWhere, stackA, stackB);
|
var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB);
|
||||||
|
|
||||||
stackA.pop();
|
stackA.pop();
|
||||||
stackB.pop();
|
stackB.pop();
|
||||||
@@ -2387,7 +2393,7 @@
|
|||||||
while (++index < length) {
|
while (++index < length) {
|
||||||
if ((noCustomizer && strictCompareFlags[index])
|
if ((noCustomizer && strictCompareFlags[index])
|
||||||
? values[index] !== object[props[index]]
|
? values[index] !== object[props[index]]
|
||||||
: !hasOwnProperty.call(object, props[index])
|
: !(props[index] in object)
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2396,7 +2402,7 @@
|
|||||||
while (++index < length) {
|
while (++index < length) {
|
||||||
var key = props[index];
|
var key = props[index];
|
||||||
if (noCustomizer && strictCompareFlags[index]) {
|
if (noCustomizer && strictCompareFlags[index]) {
|
||||||
var result = hasOwnProperty.call(object, key);
|
var result = key in object;
|
||||||
} else {
|
} else {
|
||||||
var objValue = object[key],
|
var objValue = object[key],
|
||||||
srcValue = values[index];
|
srcValue = values[index];
|
||||||
@@ -2447,7 +2453,7 @@
|
|||||||
|
|
||||||
if (isStrictComparable(value)) {
|
if (isStrictComparable(value)) {
|
||||||
return function(object) {
|
return function(object) {
|
||||||
return object != null && object[key] === value && hasOwnProperty.call(object, key);
|
return object != null && object[key] === value && key in object;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2476,7 +2482,7 @@
|
|||||||
function baseMatchesProperty(key, value) {
|
function baseMatchesProperty(key, value) {
|
||||||
if (isStrictComparable(value)) {
|
if (isStrictComparable(value)) {
|
||||||
return function(object) {
|
return function(object) {
|
||||||
return object != null && object[key] === value;
|
return object != null && object[key] === value && key in object;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return function(object) {
|
return function(object) {
|
||||||
@@ -3771,18 +3777,18 @@
|
|||||||
* @param {Array} other The other array to compare.
|
* @param {Array} other The other array to compare.
|
||||||
* @param {Function} equalFunc The function to determine equivalents of values.
|
* @param {Function} equalFunc The function to determine equivalents of values.
|
||||||
* @param {Function} [customizer] The function to customize comparing arrays.
|
* @param {Function} [customizer] The function to customize comparing arrays.
|
||||||
* @param {boolean} [isWhere] Specify performing partial comparisons.
|
* @param {boolean} [isLoose] Specify performing partial comparisons.
|
||||||
* @param {Array} [stackA] Tracks traversed `value` objects.
|
* @param {Array} [stackA] Tracks traversed `value` objects.
|
||||||
* @param {Array} [stackB] Tracks traversed `other` objects.
|
* @param {Array} [stackB] Tracks traversed `other` objects.
|
||||||
* @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
|
* @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
|
||||||
*/
|
*/
|
||||||
function equalArrays(array, other, equalFunc, customizer, isWhere, stackA, stackB) {
|
function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) {
|
||||||
var index = -1,
|
var index = -1,
|
||||||
arrLength = array.length,
|
arrLength = array.length,
|
||||||
othLength = other.length,
|
othLength = other.length,
|
||||||
result = true;
|
result = true;
|
||||||
|
|
||||||
if (arrLength != othLength && !(isWhere && othLength > arrLength)) {
|
if (arrLength != othLength && !(isLoose && othLength > arrLength)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Deep compare the contents, ignoring non-numeric properties.
|
// Deep compare the contents, ignoring non-numeric properties.
|
||||||
@@ -3792,23 +3798,23 @@
|
|||||||
|
|
||||||
result = undefined;
|
result = undefined;
|
||||||
if (customizer) {
|
if (customizer) {
|
||||||
result = isWhere
|
result = isLoose
|
||||||
? customizer(othValue, arrValue, index)
|
? customizer(othValue, arrValue, index)
|
||||||
: customizer(arrValue, othValue, index);
|
: customizer(arrValue, othValue, index);
|
||||||
}
|
}
|
||||||
if (typeof result == 'undefined') {
|
if (typeof result == 'undefined') {
|
||||||
// Recursively compare arrays (susceptible to call stack limits).
|
// Recursively compare arrays (susceptible to call stack limits).
|
||||||
if (isWhere) {
|
if (isLoose) {
|
||||||
var othIndex = othLength;
|
var othIndex = othLength;
|
||||||
while (othIndex--) {
|
while (othIndex--) {
|
||||||
othValue = other[othIndex];
|
othValue = other[othIndex];
|
||||||
result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isWhere, stackA, stackB);
|
result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB);
|
||||||
if (result) {
|
if (result) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isWhere, stackA, stackB);
|
result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3864,18 +3870,18 @@
|
|||||||
* @param {Object} other The other object to compare.
|
* @param {Object} other The other object to compare.
|
||||||
* @param {Function} equalFunc The function to determine equivalents of values.
|
* @param {Function} equalFunc The function to determine equivalents of values.
|
||||||
* @param {Function} [customizer] The function to customize comparing values.
|
* @param {Function} [customizer] The function to customize comparing values.
|
||||||
* @param {boolean} [isWhere] Specify performing partial comparisons.
|
* @param {boolean} [isLoose] Specify performing partial comparisons.
|
||||||
* @param {Array} [stackA] Tracks traversed `value` objects.
|
* @param {Array} [stackA] Tracks traversed `value` objects.
|
||||||
* @param {Array} [stackB] Tracks traversed `other` objects.
|
* @param {Array} [stackB] Tracks traversed `other` objects.
|
||||||
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
|
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
|
||||||
*/
|
*/
|
||||||
function equalObjects(object, other, equalFunc, customizer, isWhere, stackA, stackB) {
|
function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) {
|
||||||
var objProps = keys(object),
|
var objProps = keys(object),
|
||||||
objLength = objProps.length,
|
objLength = objProps.length,
|
||||||
othProps = keys(other),
|
othProps = keys(other),
|
||||||
othLength = othProps.length;
|
othLength = othProps.length;
|
||||||
|
|
||||||
if (objLength != othLength && !isWhere) {
|
if (objLength != othLength && !isLoose) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var hasCtor,
|
var hasCtor,
|
||||||
@@ -3883,7 +3889,7 @@
|
|||||||
|
|
||||||
while (++index < objLength) {
|
while (++index < objLength) {
|
||||||
var key = objProps[index],
|
var key = objProps[index],
|
||||||
result = hasOwnProperty.call(other, key);
|
result = isLoose ? key in other : hasOwnProperty.call(other, key);
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
var objValue = object[key],
|
var objValue = object[key],
|
||||||
@@ -3891,13 +3897,13 @@
|
|||||||
|
|
||||||
result = undefined;
|
result = undefined;
|
||||||
if (customizer) {
|
if (customizer) {
|
||||||
result = isWhere
|
result = isLoose
|
||||||
? customizer(othValue, objValue, key)
|
? customizer(othValue, objValue, key)
|
||||||
: customizer(objValue, othValue, key);
|
: customizer(objValue, othValue, key);
|
||||||
}
|
}
|
||||||
if (typeof result == 'undefined') {
|
if (typeof result == 'undefined') {
|
||||||
// Recursively compare objects (susceptible to call stack limits).
|
// Recursively compare objects (susceptible to call stack limits).
|
||||||
result = (objValue && objValue === othValue) || equalFunc(objValue, othValue, customizer, isWhere, stackA, stackB);
|
result = (objValue && objValue === othValue) || equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!result) {
|
if (!result) {
|
||||||
@@ -3905,7 +3911,7 @@
|
|||||||
}
|
}
|
||||||
hasCtor || (hasCtor = key == 'constructor');
|
hasCtor || (hasCtor = key == 'constructor');
|
||||||
}
|
}
|
||||||
if (!hasCtor) {
|
if (!hasCtor && !isLoose) {
|
||||||
var objCtor = object.constructor,
|
var objCtor = object.constructor,
|
||||||
othCtor = other.constructor;
|
othCtor = other.constructor;
|
||||||
|
|
||||||
@@ -8715,7 +8721,7 @@
|
|||||||
value = source[key];
|
value = source[key];
|
||||||
|
|
||||||
if (isStrictComparable(value)) {
|
if (isStrictComparable(value)) {
|
||||||
return object != null && value === object[key] && hasOwnProperty.call(object, key);
|
return object != null && value === object[key] && key in object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var values = Array(length),
|
var values = Array(length),
|
||||||
|
|||||||
@@ -9634,7 +9634,7 @@
|
|||||||
objects = [{ 'a': 1 }, { 'a': 1, 'b': 1 }, { 'a': 1, 'b': undefined }],
|
objects = [{ 'a': 1 }, { 'a': 1, 'b': 1 }, { 'a': 1, 'b': undefined }],
|
||||||
actual = _.map(objects, matches);
|
actual = _.map(objects, matches);
|
||||||
|
|
||||||
deepEqual(actual, [true, false, true]);
|
deepEqual(actual, [false, false, true]);
|
||||||
|
|
||||||
matches = _.matchesProperty('a', { 'b': undefined });
|
matches = _.matchesProperty('a', { 'b': undefined });
|
||||||
objects = [{ 'a': { 'a': 1 } }, { 'a': { 'a': 1, 'b': 1 } }, { 'a': { 'a': 1, 'b': undefined } }];
|
objects = [{ 'a': { 'a': 1 } }, { 'a': { 'a': 1, 'b': 1 } }, { 'a': { 'a': 1, 'b': undefined } }];
|
||||||
|
|||||||
Reference in New Issue
Block a user