diff --git a/lodash.js b/lodash.js index cd74fc788..4c9632d10 100644 --- a/lodash.js +++ b/lodash.js @@ -8525,36 +8525,32 @@ * // => { 'name': 'barney', 'age': 36 } */ function matches(source) { - var keyVals = pairs(source), - keyValsLength = keyVals.length; + var props = keys(source), + length = props.length, + index = length, + modes = Array(length), + vals = Array(length); - if (keyValsLength) { - var keyVal = keyVals[0], - key = keyVal[0], - value = keyVal[1]; - } - // fast path the common case of providing an object with a single - // 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); - }; + while (index--) { + var value = source[props[index]], + isDeep = value !== value || (value === 0 && 1 / value < 0) || isObject(value); + + modes[index] = isDeep; + vals[index] = isDeep ? baseClone(value, isDeep) : value; } return function(object) { - var length = keyValsLength; - if (length && object == null) { - return false; + index = length; + if (object == null) { + return !index; } - while (length--) { - keyVal = keyVals[length]; - key = keyVal[0]; - if (!(hasOwnProperty.call(object, key) && - baseIsEqual(keyVal[1], object[key], null, true))) { + while (index--) { + if (modes[index] ? !hasOwnProperty.call(object, props[index]) : vals[index] !== object[props[index]]) { + return false; + } + } + index = length; + while (index--) { + if (modes[index] ? !baseIsEqual(vals[index], object[props[index]], null, true) : !hasOwnProperty.call(object, props[index])) { return false; } } diff --git a/test/test.js b/test/test.js index 1f66af8a3..4818ba752 100644 --- a/test/test.js +++ b/test/test.js @@ -6681,8 +6681,8 @@ }); 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 } }, - otherObject = _.assign({}, object, { 'a': false, 'c': 3, 'f': { 'g': '6' } }), + var object = { 'a': false, 'b': true, 'c': '3', 'd': 4, 'e': [5], 'f': { 'g': 6 } }, + otherObject = { 'a': 0, 'b': 1, 'c': 3, 'd': '4', 'e': ['5'], 'f': { 'g': '6' } }, matches = _.matches(object); strictEqual(matches(object), true); @@ -6690,18 +6690,23 @@ }); test('should not change match behavior if `source` is augmented', 6, function() { - _.each([{ 'a': 1 }, { 'a': 1, 'b': 2 }], function(source) { - var object = _.clone(source), + _.each([{ 'a': 1, 'b': 2 }, { 'a': { 'b': 2, 'c': 3 } }], function(source, index) { + var object = _.cloneDeep(source), matches = _.matches(source); - strictEqual(matches(object), true); + strictEqual(matches(object), true, 'a' + index); - source.a = 2; - source.b = 1; - source.c = 3; - - strictEqual(matches(object), true); - strictEqual(matches(source), false); + if (index) { + source.a.b = 1; + source.a.c = 2; + source.a.d = 3; + } else { + 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 } }; - var expected = [object.x, object.z], - actual = _.where(object, { 'a': 1 }); + var actual = _.where(object, { 'a': 1 }), + expected = [object.x, object.z]; deepEqual(actual, expected); });