什么是最有效的方式来克隆一个JavaScript对象?我已经看到obj = eval(uneval(o));被使用,但它是非标准的,仅支持Firefox.我做了事情,如obj = JSON.parse(JSON.stringify(o));但质疑效率。


当前回答

深复制对象在JavaScript(我认为最好的和最简单的)

使用 JSON.parse(JSON.stringify(对象));

var obj = { 
  a: 1,
  b: { 
    c: 2
  }
}
var newObj = JSON.parse(JSON.stringify(obj));
obj.b.c = 20;
console.log(obj); // { a: 1, b: { c: 20 } }
console.log(newObj); // { a: 1, b: { c: 2 } } 

二、使用创造的方法

function cloneObject(obj) {
    var clone = {};
    for(var i in obj) {
        if(obj[i] != null &&  typeof(obj[i])=="object")
            clone[i] = cloneObject(obj[i]);
        else
            clone[i] = obj[i];
    }
    return clone;
}

var obj = { 
  a: 1,
  b: { 
    c: 2
  }
}
var newObj = cloneObject(obj);
obj.b.c = 20;

console.log(obj); // { a: 1, b: { c: 20 } }
console.log(newObj); // { a: 1, b: { c: 2 } } 

使用 Lo-Dash 的 _.cloneDeep 链接 lodash

var obj = { 
  a: 1,
  b: { 
    c: 2
  }
}

var newObj = _.cloneDeep(obj);
obj.b.c = 20;
console.log(obj); // { a: 1, b: { c: 20 } }
console.log(newObj); // { a: 1, b: { c: 2 } } 

使用 Object.assign() 方法

var obj = { 
  a: 1,
  b: 2
}

var newObj = _.clone(obj);
obj.b = 20;
console.log(obj); // { a: 1, b: 20 }
console.log(newObj); // { a: 1, b: 2 }  

但是,当

var obj = { 
  a: 1,
  b: { 
    c: 2
  }
}

var newObj = Object.assign({}, obj);
obj.b.c = 20;
console.log(obj); // { a: 1, b: { c: 20 } }
console.log(newObj); // { a: 1, b: { c: 20 } } --> WRONG
// Note: Properties on the prototype chain and non-enumerable properties cannot be copied.

使用 Underscore.js _.clone 链接 Underscore.js

var obj = { 
  a: 1,
  b: 2
}

var newObj = _.clone(obj);
obj.b = 20;
console.log(obj); // { a: 1, b: 20 }
console.log(newObj); // { a: 1, b: 2 }  

但是,当

var obj = { 
  a: 1,
  b: { 
    c: 2
  }
}

var newObj = _.cloneDeep(obj);
obj.b.c = 20;
console.log(obj); // { a: 1, b: { c: 20 } }
console.log(newObj); // { a: 1, b: { c: 20 } } --> WRONG
// (Create a shallow-copied clone of the provided plain object. Any nested objects or arrays will be copied by reference, not duplicated.)

JSBEN.CH 性能 平衡 游戏场 1~3 http://jsben.ch/KVQLd

其他回答

我认为这是最好的解决方案,如果你想通用你的对象克隆算法,它可以用与或没有jQuery,虽然我建议你放弃jQuery的扩展方法,如果你想你克隆的对象有相同的“类”与原始一个。

function clone(obj){
    if(typeof(obj) == 'function')//it's a simple function
        return obj;
    //of it's not an object (but could be an array...even if in javascript arrays are objects)
    if(typeof(obj) !=  'object' || obj.constructor.toString().indexOf('Array')!=-1)
        if(JSON != undefined)//if we have the JSON obj
            try{
                return JSON.parse(JSON.stringify(obj));
            }catch(err){
                return JSON.parse('"'+JSON.stringify(obj)+'"');
            }
        else
            try{
                return eval(uneval(obj));
            }catch(err){
                return eval('"'+uneval(obj)+'"');
            }
    // I used to rely on jQuery for this, but the "extend" function returns
    //an object similar to the one cloned,
    //but that was not an instance (instanceof) of the cloned class
    /*
    if(jQuery != undefined)//if we use the jQuery plugin
        return jQuery.extend(true,{},obj);
    else//we recursivley clone the object
    */
    return (function _clone(obj){
        if(obj == null || typeof(obj) != 'object')
            return obj;
        function temp () {};
        temp.prototype = obj;
        var F = new temp;
        for(var key in obj)
            F[key] = clone(obj[key]);
        return F;
    })(obj);            
}

这是一个回归的解决方案:

obj = { a: { b: { c: { d: ['1', '2'] } } }, e: 'Saeid' } const Clone = function (obj) { const container = Array.isArray(obj) ? [] : {} const keys = Object.keys(obj) for (let i = 0; i < keys.length; i++) { const key = keys[i] if(typeof obj[key] == 'object') { container[key] = Clone(obj[key]) } else container[key] = obj[key].slice() } return container } console.log(Clone(obj))

克罗克福德建议(我更喜欢)使用此功能:

function object(o) {
    function F() {}
    F.prototype = o;
    return new F();
}

var newObject = object(oldObject);

它是干净的,工作如预期,你不需要图书馆。


编辑:

这是一个对 Object.create 的聚合物,所以你也可以使用它。

var newObject = Object.create(oldObject);

注意: 如果你使用其中的一些,你可能有问题与某些 iteration谁使用 hasOwnProperty. 因为,创建创造新的空的对象,继承旧的对象. 但它仍然有用和实用的克隆对象。

例如,如果 oldObject.a = 5;

newObject.a; // is 5

但:

oldObject.hasOwnProperty(a); // is true
newObject.hasOwnProperty(a); // is false

下面是同一个对象的两个例子,我发现了它,目前正在使用它,它很简单,易于使用。

var objToCreate = JSON.parse(JSON.stringify(cloneThis));

通过提出新的方法 Object.fromEntries(),它支持一些浏览器的更新的版本(参考)。

const obj = { key1: {key11: “key11”, key12: “key12”, key13: {key131: 22}}, key2: {key21: “key21”, key22: “key22”}, key3: “key3”, key4: [1,2,3, {key: “value”} } const cloneObj = (obj) => { if (Object(obj)!== obj) return obj; other if (Array.isArray(obj)) return obj.map(cloneObj); return Object.fromEntries(Object.entries(obj).map(([k,v])