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


当前回答

扩展操作器... (原始序列 - 仅) 序列(0) (原始序列 - 仅) 序列() (原始序列 - 仅) concat() (原始序列 - 仅) 定制功能,如下所示(每个序列) jQuery 的 $.extend() (每个序列) JSON.parse(JSON.stringify()) (原始和字面序列 - 仅) Underscore 的 _.clone() (原始和字面序列 - 仅) Lodash 的 _.cloneDeep() (每个序列)

let arr1a = [1, 'a', true];

let arr1b = [...arr1a];

而且在哪裡 slice() 比 concat( 有更好的性能: https://jsbench.me/x5ktn7o94d/

let arr1c = arr1a.splice(0);
let arr1d = arr1a.slice();
let arr1e = arr1a.concat();

let arr2a = [1, 'a', true, {}, []];
let arr2b = JSON.parse(JSON.stringify(arr2a));

let arr3a = [1, 'a', true, {}, [], new Object()];

function copy(aObject) {
  // Prevent undefined objects
  // if (!aObject) return aObject;

  let bObject = Array.isArray(aObject) ? [] : {};

  let value;
  for (const key in aObject) {

    // Prevent self-references to parent object
    // if (Object.is(aObject[key], aObject)) continue;
    
    value = aObject[key];

    bObject[key] = (typeof value === "object") ? copy(value) : value;
  }

  return bObject;
}

let arr3b = copy(arr3a);

或使用第三方实用功能:

let arr3c = $.extend(true, [], arr3a); // jQuery Extend
let arr3d = _.cloneDeep(arr3a); // Lodash

注意: jQuery 的 $.extend 也比 JSON.parse(JSON.stringify() 表现更好):

其他回答

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

它可以用于浏览器以及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' } }

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

因为回归只是太昂贵的JavaScript,我发现的大多数答案是使用回归,而JSON方法将错过非JSON转换部分(功能等)。所以我做了一些研究,并发现这个拖拉机技术避免它。

/*
 * Trampoline to avoid recursion in JavaScript, see:
 *     https://www.integralist.co.uk/posts/functional-recursive-javascript-programming/
 */
function trampoline() {
    var func = arguments[0];
    var args = [];
    for (var i = 1; i < arguments.length; i++) {
        args[i - 1] = arguments[i];
    }

    var currentBatch = func.apply(this, args);
    var nextBatch = [];

    while (currentBatch && currentBatch.length > 0) {
        currentBatch.forEach(function(eachFunc) {
            var ret = eachFunc();
            if (ret && ret.length > 0) {
                nextBatch = nextBatch.concat(ret);
            }
        });

        currentBatch = nextBatch;
        nextBatch = [];
    }
};

/*
 *  Deep clone an object using the trampoline technique.
 *
 *  @param target {Object} Object to clone
 *  @return {Object} Cloned object.
 */
function clone(target) {
    if (typeof target !== 'object') {
        return target;
    }
    if (target == null || Object.keys(target).length == 0) {
        return target;
    }

    function _clone(b, a) {
        var nextBatch = [];
        for (var key in b) {
            if (typeof b[key] === 'object' && b[key] !== null) {
                if (b[key] instanceof Array) {
                    a[key] = [];
                }
                else {
                    a[key] = {};
                }
                nextBatch.push(_clone.bind(null, b[key], a[key]));
            }
            else {
                a[key] = b[key];
            }
        }
        return nextBatch;
    };

    var ret = target instanceof Array ? [] : {};
    (trampoline.bind(null, _clone))(target, ret);
    return ret;
};

通过提出新的方法 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])

当您的对象被粘贴并包含数据对象、其他结构化对象或某种属性对象等时,使用 JSON.parse(JSON.stringify(object)) 或 Object.assign({}, obj) 或 $.extend(true, {}, obj) 不会工作。

var obj = {a: 25, b: {a: 1, b: 2}, c: new Date(), d: anotherNestedObject };
var A = _.cloneDeep(obj);

现在 A 将是您的新的 Obj 克隆,没有任何参考。

单线 ECMAScript 6 解决方案(特殊对象类型如 Date/Regex 未处理):

const clone = (o) => typeof o === 'object' && o!== null? // only clone objects (Array.isArray(o)? // if cloning an array o.map(e => clone(e)) : // clone each of its elements Object.keys(o).reduce( // otherwise reduce every key in the object (r, k) => (r[k] = clone(o[k]), r), {} // and save its cloned value