Skip to main content

Recursively merge (aka. deep copy) the contents of two or more objects together into the first object.

/**
 * Deep Extend
 *
 * Recursively merge (aka. deep copy) the contents of two or more objects
 * together into the first object.
 *
 * When two or more object arguments are supplied to deepExtend(), properties
 * from all of the objects are added to the target object. Arguments that are
 * null or undefined are ignored.
 *
 * Keep in mind that the targetObject will be modified and returned. If,
 * however, you want to preserve both of the original objects, you can do so by
 * passing an empty object as the targetObject.
 *
 * From: http://youmightnotneedjquery.com/#deep_extend
 * Related: https://api.jquery.com/jquery.extend/
 *
 * @param {Object} targetObject The object to extend or receive new properties.
 * @return {Object} The contents of two or more objects together into the first object (targetObject).
 *
 * @example
 *     deepExtend({}, object1, object2);
 */
const deepExtend = function(targetObject) {
    targetObject = targetObject || {};

    for (let i = 1; i < arguments.length; i++) {
        const obj = arguments[i];
        if (!obj) {
            continue;
        }

        for (const key in obj) {
            if (Object.prototype.hasOwnProperty.call(obj, key)) {
                if (typeof obj[key] === "object") {
                    if (obj[key] instanceof Array) {
                        targetObject[key] = obj[key].slice(0);
                    } else {
                        targetObject[key] = deepExtend(
                            targetObject[key],
                            obj[key]
                        );
                    }
                } else {
                    targetObject[key] = obj[key];
                }
            }
        }
    }

    return targetObject;
};