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


当前回答

只有在您可以使用 ECMAScript 6 或 transpilers 时。

特性:

将不会在复制时发射输入/输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输入输

代码:

function clone(target, source){

    for(let key in source){

        // Use getOwnPropertyDescriptor instead of source[key] to prevent from trigering setter/getter.
        let descriptor = Object.getOwnPropertyDescriptor(source, key);
        if(descriptor.value instanceof String){
            target[key] = new String(descriptor.value);
        }
        else if(descriptor.value instanceof Array){
            target[key] = clone([], descriptor.value);
        }
        else if(descriptor.value instanceof Object){
            let prototype = Reflect.getPrototypeOf(descriptor.value);
            let cloneObject = clone({}, descriptor.value);
            Reflect.setPrototypeOf(cloneObject, prototype);
            target[key] = cloneObject;
        }
        else {
            Object.defineProperty(target, key, descriptor);
        }
    }
    let prototype = Reflect.getPrototypeOf(source);
    Reflect.setPrototypeOf(target, prototype);
    return target;
}

其他回答

var clone = function() {
    var newObj = (this instanceof Array) ? [] : {};
    for (var i in this) {
        if (this[i] && typeof this[i] == "object") {
            newObj[i] = this[i].clone();
        }
        else
        {
            newObj[i] = this[i];
        }
    }
    return newObj;
}; 

Object.defineProperty( Object.prototype, "clone", {value: clone, enumerable: false});

Object.assign({},sourceObj)只有在其属性没有参考类型密钥时才会克隆对象。

obj={a:"lol",b:["yes","no","maybe"]}
clonedObj = Object.assign({},obj);

clonedObj.b.push("skip")// changes will reflected to the actual obj as well because of its reference type.
obj.b //will also console => yes,no,maybe,skip

因此,对于深度克隆,不可能以这种方式实现。

最有效的解决方案是

var obj = Json.stringify(yourSourceObj)
var cloned = Json.parse(obj);

这通常不是最有效的解决方案,但它是我需要的。

function clone(obj, clones) {
    // Makes a deep copy of 'obj'. Handles cyclic structures by
    // tracking cloned obj's in the 'clones' parameter. Functions 
    // are included, but not cloned. Functions members are cloned.
    var new_obj,
        already_cloned,
        t = typeof obj,
        i = 0,
        l,
        pair; 

    clones = clones || [];

    if (obj === null) {
        return obj;
    }

    if (t === "object" || t === "function") {

        // check to see if we've already cloned obj
        for (i = 0, l = clones.length; i < l; i++) {
            pair = clones[i];
            if (pair[0] === obj) {
                already_cloned = pair[1];
                break;
            }
        }

        if (already_cloned) {
            return already_cloned; 
        } else {
            if (t === "object") { // create new object
                new_obj = new obj.constructor();
            } else { // Just use functions as is
                new_obj = obj;
            }

            clones.push([obj, new_obj]); // keep track of objects we've cloned

            for (key in obj) { // clone object members
                if (obj.hasOwnProperty(key)) {
                    new_obj[key] = clone(obj[key], clones);
                }
            }
        }
    }
    return new_obj || obj;
}

自行车测试...

a = []
a.push("b", "c", a)
aa = clone(a)
aa === a //=> false
aa[2] === a //=> false
aa[2] === a[2] //=> false
aa[2] === aa //=> true

功能测试...

f = new Function
f.a = a
ff = clone(f)
ff === f //=> true
ff.a === a //=> false

如果您正在使用它,UnderScore.js图书馆有一个克隆方法。

var newObject = _.clone(oldObject);

有一个图书馆(被称为“克隆”),这做得很好,它提供了我所知道的任意物体的最完整的重复克隆/复制,它也支持循环参考,而其他答案却不受覆盖。

它可以用于浏览器以及Node.js。

下面是如何使用它的例子:

安装它与

npm install clone

或者用Ender包装。

ender build clone [...]

您也可以手动下载源代码。

然后你可以在源代码中使用它。

var clone = require('clone');

var a = { foo: { bar: 'baz' } };  // inital value of a
var b = clone(a);                 // clone a -> b
a.foo.bar = 'foo';                // change a

console.log(a);                   // { foo: { bar: 'foo' } }
console.log(b);                   // { foo: { bar: 'baz' } }

(解答:我是图书馆的作者。