$.extend 的一种变体,它保留具有未定义值的属性?

A variant of $.extend that keeps properties with undefined values?

我看到这段代码:

$.extend(true, {}, { data: undefined });

returns 空对象:{}。我在 Chrome 45.0.2454.101(64 位)上用 jQuery 2.1.1 测试了这个。

是否有 $.extend 的变体可以保留 undefined 值的属性?能举个例子吗?

非常感谢! :-)

无法使用 Jquery 扩展方法。 API 文档中明确提到 https://api.jquery.com/jquery.extend/

When two or more object arguments are supplied to $.extend(), properties from all of the objects are added to the target object. Arguments that are null or undefined are ignored.

正如问题评论中所写,jQuery 文档提到 jQuery 实现会忽略具有 undefined 值的属性。在我的代码中,我不想使用另一个库,例如 lodash,所以我从 jQuery 的 $.extend 中获取了代码,并稍微更改了它以保留 undefined 的属性] 值。

/**
 * extend
 * A jQuery $.extend implementation changed to keep properties with
 * undefined values. The original source code was taken from here:
 * https://github.com/jquery/jquery/blob/64f7d10980a5e9f2862f1239a37d95e6c39e37ec/src/core.js
 * and the original documentation was taken from here:
 * http://api.jquery.com/jQuery.extend/
 *
 * Merge the contents of two or more objects together into the first object.
 *
 * @name extend
 * @function
 * @param {Boolean} deep If true, the merge becomes recursive (aka. deep copy).
 * @param {Object} target The object to extend. It will receive the new properties.
 * @param {Object} object1 An object containing additional properties to merge in.
 * @param {Object} objectN Additional objects containing properties to merge in.
 * @return {Object} The modified target object.
 */
function extend() {
    var options, name, src, copy, copyIsArray, clone,
        target = arguments[0] || {},
        i = 1,
        length = arguments.length,
        deep = false;

    // Handle a deep copy situation
    if (typeof target === "boolean") {
        deep = target;

        // Skip the boolean and the target
        target = arguments[i] || {};
        i++;
    }

    // Handle case when target is a string or something (possible in deep copy)
    if (typeof target !== "object" && !$.isFunction(target)) {
        target = {};
    }

    // Extend jQuery itself if only one argument is passed
    if (i === length) {
        target = this;
        i--;
    }

    for (; i < length; i++) {
        // Only deal with non-null/undefined values
        if ((options = arguments[i]) != null) {
            // Extend the base object
            for (name in options) {
                src = target[name];
                copy = options[name];

                // Prevent never-ending loop
                if (target === copy) {
                    continue;
                }

                // Recurse if we're merging plain objects or arrays
                if (deep && copy && ($.isPlainObject(copy) || (copyIsArray = $.isArray(copy)))) {
                    if (copyIsArray) {
                        copyIsArray = false;
                        clone = src && $.isArray(src) ? src : [];

                    } else {
                        clone = src && $.isPlainObject(src) ? src : {};
                    }

                    // Never move original objects, clone them
                    target[name] = jQuery.extend(deep, clone, copy);

                // Modified this else branch to allow undefined values
                } else {
                    target[name] = copy;
                }
            }
        }
    }

    // Return the modified object
    return target;
}