Creates a new object from the combination of two or more objects.

/**
 * Creates a new object from the combination of two or more objects.
 *
 * Use Array.prototype.reduce() combined with Object.keys(obj) to iterate
 * over all objects and keys. Use hasOwnProperty() and concat() to append
 * values for keys existing in multiple objects.
 *
 * @param {...} objs
 * @returns {*}
 *
 * @example
 *  const object = { a: [{ x: 2 }, { y: 4 }], b: 1 };
 *  const other = { a: { z: 3 }, b: [2, 3], c: "foo" };
 *  merge(object, other); // { a: [{x: 2}, {y: 4}, {z: 3}], b: [1, 2, 3], c: "foo" }
 *
 * @link https://www.30secondsofcode.org/js/s/merge/
 */
const merge = (...objs) =>
    [...objs].reduce(
        (acc, obj) =>
            Object.keys(obj).reduce((a, k) => {
                acc[k] = Object.prototype.hasOwnProperty.call(acc, k)
                    ? [].concat(acc[k]).concat(obj[k])
                    : obj[k];
                return acc;
            }, {}),
        {}
    );

//
// Example usage:

const object = { a: [{ x: 2 }, { y: 4 }], b: 1 };
const other = { a: { z: 3 }, b: [2, 3], c: "foo" };
merge(object, other); // { a: [{x: 2}, {y: 4}, {z: 3}], b: [1, 2, 3], c: "foo" }