Ensure _.match deep comparison isn't affected by changes to source objects.

This commit is contained in:
John-David Dalton
2014-07-09 00:43:50 -07:00
parent 30f256aad2
commit 4606c8092f
2 changed files with 40 additions and 39 deletions

View File

@@ -8525,36 +8525,32 @@
* // => { 'name': 'barney', 'age': 36 } * // => { 'name': 'barney', 'age': 36 }
*/ */
function matches(source) { function matches(source) {
var keyVals = pairs(source), var props = keys(source),
keyValsLength = keyVals.length; length = props.length,
index = length,
modes = Array(length),
vals = Array(length);
if (keyValsLength) { while (index--) {
var keyVal = keyVals[0], var value = source[props[index]],
key = keyVal[0], isDeep = value !== value || (value === 0 && 1 / value < 0) || isObject(value);
value = keyVal[1];
} modes[index] = isDeep;
// fast path the common case of providing an object with a single vals[index] = isDeep ? baseClone(value, isDeep) : value;
// property containing a primitive value
if (keyValsLength == 1 && value === value && !isObject(value)) {
return function(object) {
if (object == null) {
return false;
}
// treat `-0` vs. `+0` as not equal
var other = object[key];
return value === other && (value !== 0 || (1 / value == 1 / other)) && hasOwnProperty.call(object, key);
};
} }
return function(object) { return function(object) {
var length = keyValsLength; index = length;
if (length && object == null) { if (object == null) {
return false; return !index;
} }
while (length--) { while (index--) {
keyVal = keyVals[length]; if (modes[index] ? !hasOwnProperty.call(object, props[index]) : vals[index] !== object[props[index]]) {
key = keyVal[0]; return false;
if (!(hasOwnProperty.call(object, key) && }
baseIsEqual(keyVal[1], object[key], null, true))) { }
index = length;
while (index--) {
if (modes[index] ? !baseIsEqual(vals[index], object[props[index]], null, true) : !hasOwnProperty.call(object, props[index])) {
return false; return false;
} }
} }

View File

@@ -6681,8 +6681,8 @@
}); });
test('should compare a variety of `source` object values', 2, function() { test('should compare a variety of `source` object values', 2, function() {
var object = { 'a': false, 'b': true, 'c': '3', 'd': 4, 'e': [5], 'f': { 'g': 6 } }, var object = { 'a': false, 'b': true, 'c': '3', 'd': 4, 'e': [5], 'f': { 'g': 6 } },
otherObject = _.assign({}, object, { 'a': false, 'c': 3, 'f': { 'g': '6' } }), otherObject = { 'a': 0, 'b': 1, 'c': 3, 'd': '4', 'e': ['5'], 'f': { 'g': '6' } },
matches = _.matches(object); matches = _.matches(object);
strictEqual(matches(object), true); strictEqual(matches(object), true);
@@ -6690,18 +6690,23 @@
}); });
test('should not change match behavior if `source` is augmented', 6, function() { test('should not change match behavior if `source` is augmented', 6, function() {
_.each([{ 'a': 1 }, { 'a': 1, 'b': 2 }], function(source) { _.each([{ 'a': 1, 'b': 2 }, { 'a': { 'b': 2, 'c': 3 } }], function(source, index) {
var object = _.clone(source), var object = _.cloneDeep(source),
matches = _.matches(source); matches = _.matches(source);
strictEqual(matches(object), true); strictEqual(matches(object), true, 'a' + index);
source.a = 2; if (index) {
source.b = 1; source.a.b = 1;
source.c = 3; source.a.c = 2;
source.a.d = 3;
strictEqual(matches(object), true); } else {
strictEqual(matches(source), false); source.a = 2;
source.b = 1;
source.c = 3;
}
strictEqual(matches(object), true, 'b' + index);
strictEqual(matches(source), false, 'c' + index);
}); });
}); });
@@ -10801,8 +10806,8 @@
'z': { 'a': 1, 'b': 2 } 'z': { 'a': 1, 'b': 2 }
}; };
var expected = [object.x, object.z], var actual = _.where(object, { 'a': 1 }),
actual = _.where(object, { 'a': 1 }); expected = [object.x, object.z];
deepEqual(actual, expected); deepEqual(actual, expected);
}); });