Strange / unexpected behavior of object.merge
leider opened this issue · comments
The following test fails, because a property with a value of 'undefined' is treated differently from an undefined property. This is very misleading. It finally leads to a build problem in tools using bower. See rse/grunt-bower-install-simple#8
it('should ignore "undefined" properties when merging', function () {
var obj1 = {a: 0, b: 3};
var obj2 = {a: 2};
var obj3 = {a: 2, b: undefined};
var out = {a: 2, b: 3};
expect( merge(obj1, obj2)).toEqual( out );
expect( merge(obj1, obj3)).toEqual( out );
});
The second expect
will fail.
You can clearly state: "works as specified" and closing this issue. Then a few words in the docs / examples would be helpful.
Could be easily fixed by ignoring the value "undefined" inside the implementation:
define(['./hasOwn', '../lang/deepClone', '../lang/isObject'], function (hasOwn, deepClone, isObject) {
/**
* Deep merge objects.
*/
function merge() {
var i = 1,
key, val, obj, target;
// make sure we don't modify source element and it's properties
// objects are passed by reference
target = deepClone( arguments[0] );
while (obj = arguments[i++]) {
for (key in obj) {
if ( ! hasOwn(obj, key) ) {
continue;
}
val = obj[key];
if (val === undefined) {
continue;
}
if ( isObject(val) && isObject(target[key]) ){
// inception, deep merge objects
target[key] = merge(target[key], val);
} else {
// make sure arrays, regexp, date, objects are cloned
target[key] = deepClone(val);
}
}
}
return target;
}
return merge;
});
One more thing: 'No, I do not want to place a pull request.'
I'm still unsure on what would make more sense.. if you think about it, the current behavior is the correct behavior (override property if value is set - even if value is undefined
). But I can see that it is confusing in some cases and that it can lead to unexpected problems. Let's see what other people have to comment about it.
I think your statement "the current behavior is the correct behavior" makes sense. Changing that could set a big wheel in motion. Maybe you'd want to check all your functions for issues like these?
If I was you I'd leave everything as it is and add some examples / tests that clearly show this behavior.
I think the current behaviour makes more sense but yes, the documentation should perhaps state that properties with nullish values (null/undefined) are treated like any other property value.