如何正确克隆一个JavaScript对象?

3720
我有一个对象 x。我想将它作为对象 y 复制,使得对 y 的更改不会修改 x。我意识到,复制从内置 JavaScript 对象派生的对象会导致额外的、不必要的属性。这不是问题,因为我要复制的是我自己通过字面量构造的对象。
如何正确地克隆 JavaScript 对象?

34
看这个问题:https://dev59.com/83VD5IYBdhLWcg3wAGiD这个问题是关于如何克隆JavaScript对象的,你需要找到一种高效的方法来实现这个目标。 - Niyaz
289
对于 JSON,我使用 mObj=JSON.parse(JSON.stringify(jsonObject)); - Lord Loh.
78
我不明白为什么没有人建议使用 Object.create(o),它完全满足了作者的要求。 - froginvasion
59
var x = { deep: { key: 1 } }; var y = Object.create(x); x.deep.key = 2; 执行完这段代码后,y.deep.key 的值也会变成2,因此 Object.create 不能用于克隆对象。 - Ruben Stolk
23
@r3wt那样做行不通...请先对解决方案进行基本测试再发帖。 - user3275211
显示剩余21条评论
82个回答

1
你可以克隆对象而不修改父对象 -
    /** [Object Extend]*/
    ( typeof Object.extend === 'function' ? undefined : ( Object.extend = function ( destination, source ) {
        for ( var property in source )
            destination[property] = source[property];
        return destination;
    } ) );
    /** [/Object Extend]*/
    /** [Object clone]*/
    ( typeof Object.clone === 'function' ? undefined : ( Object.clone = function ( object ) {
        return this.extend( {}, object );
    } ) );
    /** [/Object clone]*/

    let myObj = {
        a:1, b:2, c:3, d:{
            a:1, b:2, c:3
        }
    };

    let clone = Object.clone( myObj );

    clone.a = 10;

    console.log('clone.a==>', clone.a); //==> 10

    console.log('myObj.a==>', myObj.a); //==> 1 // object not modified here

    let clone2 = Object.clone( clone );

    clone2.a = 20;

    console.log('clone2.a==>', clone2.a); //==> 20

    console.log('clone.a==>', clone.a); //==> 10 // object not modified here

1
如果您正在使用TypeScript,需要支持旧的Web浏览器(因此无法使用Object.assign),并且没有使用具有内置克隆方法的库,则可以在几行代码中创建一个combine助手。它将组合对象,如果您只有一个对象,则只需克隆它。
/** Creates a new object that combines the properties of the specified objects. */
function combine(...objs: {}[]) {
    const combined = {};
    objs.forEach(o => Object.keys(o).forEach(p => combined[p] = o[p]));
    return combined;
}

1

简短而精炼:

let clone = Object.fromEntries(Object.entries(obj));

演示:

let obj = {a: 'b'};
let clone = Object.fromEntries(Object.entries(obj));

clone.a = 'c';

console.log(obj, clone);


1
这会创建你的obj新副本(而不仅仅是引用)。
let myCopy = JSON.parse(JSON.stringify(obj)); 

_.cloneDeep(obj)更高效地工作。


1

2
实际上,Python的对象序列化通过跟踪已处理过的对象图中的节点来处理循环引用。您可以使用该方法来实现强大的复制例程。不过,这需要更多的工作! - A. Levy

1
你可以使用rest操作符来克隆数组或对象。
let myObj = {1: 100, 'a': 200};

let clone = {...myObj}; 

clone.a = 300;

console.log(clone.a) // Output :- 300
console.log(myObj.a) // Output :- 200

请注意,这只会执行“浅克隆”操作,https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#spread_in_object_literals - typekev

1

我不知道这种情况不适用于哪些情况,但是它让我得到了一个数组的副本。我觉得它很可爱:) 希望能帮到你

copiedArr = origArr.filter(function(x){return true})

1
var x = {'e': 2, 'd': 8, 'b': 5};

const y = {};
for(let key in x) {
    y[key] = x[key];
}
console.log(y); // =>>> {e: 2, d: 8, b: 5}

const z = {};
Object.keys(x).forEach(key => {
    z[key] = x[key];
});
console.log(z); // =>>> {e: 2, d: 8, b: 5}

const w = {};
for(let i = 0; i < Object.keys(x).length; i++) {
    w[Object.keys(x)[i]] = x[Object.keys(x)[i]];
}
console.log(w); // =>>> {e: 2, d: 8, b: 5}

const v = {};
for(let key of Object.keys(x)) {
    v[key] = x[key];
}
console.log(v); // =>>> {e: 2, d: 8, b: 5}

x['q'] = 100;   // Altering x will not affect the other objects

console.log(x); // =>>> {e: 2, d: 8, b: 5, q: 100}
console.log(y); // =>>> {e: 2, d: 8, b: 5}
console.log(z); // =>>> {e: 2, d: 8, b: 5}
console.log(w); // =>>> {e: 2, d: 8, b: 5}
console.log(v); // =>>> {e: 2, d: 8, b: 5}

1
我认为最简单的方法是:
let newUser={...user};

在这里,'newUser' 是 'user' 对象的一个克隆。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接