mout / mout

Modular JavaScript Utilities

Home Page:http://moutjs.com/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.