两个对象。assign和Object spread只做浅合并。

这个问题的一个例子:

// No object nesting
const x = { a: 1 }
const y = { b: 1 }
const z = { ...x, ...y } // { a: 1, b: 1 }

输出是您所期望的。然而,如果我尝试这样做:

// Object nesting
const x = { a: { a: 1 } }
const y = { a: { b: 1 } }
const z = { ...x, ...y } // { a: { b: 1 } }

而不是

{ a: { a: 1, b: 1 } }

你得到

{ a: { b: 1 } }

X被完全覆盖,因为扩展语法只覆盖了一层。这与Object.assign()相同。

有办法做到这一点吗?


当前回答

使用这个函数:

merge(target, source, mutable = false) {
        const newObj = typeof target == 'object' ? (mutable ? target : Object.assign({}, target)) : {};
        for (const prop in source) {
            if (target[prop] == null || typeof target[prop] === 'undefined') {
                newObj[prop] = source[prop];
            } else if (Array.isArray(target[prop])) {
                newObj[prop] = source[prop] || target[prop];
            } else if (target[prop] instanceof RegExp) {
                newObj[prop] = source[prop] || target[prop];
            } else {
                newObj[prop] = typeof source[prop] === 'object' ? this.merge(target[prop], source[prop]) : source[prop];
            }
        }
        return newObj;
    }

其他回答

你可以使用Lodash合并:

Var对象= { 'a': [{'b': 2}, {'d': 4}] }; Var other = { 'a': [{'c': 3}, {'e': 5}] }; console.log(_。合并(对象,其他)); / / = > {a: [{b: 2,“c”:3},{' d ': 4,“e”:5}]} < script src = " https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js " > < /脚本>

如果你正在使用ImmutableJS,你可以使用mergeDeep:

fromJS(options).mergeDeep(options2).toJS();

如果您想合并多个普通对象(不要修改输入对象)。基于对象。分配polyfill

function isPlainObject(a) { return (!!a) && (a.constructor === Object); } function merge(target) { let to = Object.assign({}, target); for (let index = 1; index < arguments.length; index++) { let nextSource = arguments[index]; if (nextSource !== null && nextSource !== undefined) { for (let nextKey in nextSource) { // Avoid bugs when hasOwnProperty is shadowed if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { if (isPlainObject(to[nextKey]) && isPlainObject(nextSource[nextKey])) { to[nextKey] = merge(to[nextKey], nextSource[nextKey]); } else { to[nextKey] = nextSource[nextKey]; } } } } } return to; } // Usage var obj1 = { a: 1, b: { x: 2, y: { t: 3, u: 4 } }, c: "hi" }; var obj2 = { b: { x: 200, y: { u: 4000, v: 5000 } } }; var obj3 = { c: "hello" }; console.log("result", merge(obj1, obj2, obj3)); console.log("obj1", obj1); console.log("obj2", obj2); console.log("obj3", obj3);

如果你想合并有限的深度

function isPlainObject(a) { return (!!a) && (a.constructor === Object); } function merge(target) { let to = Object.assign({}, target); const hasDepth = arguments.length > 2 && typeof arguments[arguments.length - 1] === 'number'; const depth = hasDepth ? arguments[arguments.length - 1] : Infinity; const lastObjectIndex = hasDepth ? arguments.length - 2 : arguments.length - 1; for (let index = 1; index <= lastObjectIndex; index++) { let nextSource = arguments[index]; if (nextSource !== null && nextSource !== undefined) { for (let nextKey in nextSource) { // Avoid bugs when hasOwnProperty is shadowed if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { if (depth > 0 && isPlainObject(to[nextKey]) && isPlainObject(nextSource[nextKey])) { to[nextKey] = merge(to[nextKey], nextSource[nextKey], depth - 1); } else { to[nextKey] = nextSource[nextKey]; } } } } } return to; } // Usage var obj1 = { a: 1, b: { x: 2, y: { t: 3, u: 4, z: {zzz: 100} } }, c: "hi" }; var obj2 = { b: { y: { u: 4000, v: 5000, z: {} } } }; var obj3 = { c: "hello" }; console.log('deep 0', merge(obj1, obj2, obj3, 0)); console.log('deep 1', merge(obj1, obj2, obj3, 1)); console.log('deep 2', merge(obj1, obj2, obj3, 2)); console.log('deep 2', merge(obj1, obj2, obj3, 4));

有一个lodash包专门处理对象的深度克隆。这样做的好处是不需要包含整个lodash库。

它叫lodash.clonedeep

在nodejs中,这种用法是这样的

var cloneDeep = require('lodash.clonedeep');
 
const newObject = cloneDeep(oldObject);

在ReactJS中,用法是

import cloneDeep from 'lodash/cloneDeep';

const newObject = cloneDeep(oldObject);

查看这里的文档。如果您对它的工作原理感兴趣,请查看这里的源文件

这很简单,也很有效:

let item = {
    firstName: 'Jonnie',
    lastName: 'Walker',
    fullName: function fullName() {
            return 'Jonnie Walker';
    }
Object.assign(Object.create(item), item);

解释:

create()创建新对象。如果你传递参数给函数,它将创建你的对象与其他对象的原型。如果你在一个对象的原型上有任何函数它们会被传递给另一个对象的原型。

object .assign()合并两个对象并创建一个全新的对象,它们不再有引用。这个例子对我来说很好。