Каков наиболее эффективный способ глубокого клонирования объекта в JavaScript? - PullRequest
5052 голосов
/ 23 сентября 2008

Какой самый эффективный способ клонировать объект JavaScript? Я видел, как используется obj = eval(uneval(o));, но это нестандартно и поддерживается только Firefox .

Я делал такие вещи, как obj = JSON.parse(JSON.stringify(o));, но ставлю под сомнение эффективность.

Я также видел функции рекурсивного копирования с различными недостатками.
Я удивлен, что канонического решения не существует.

Ответы [ 74 ]

0 голосов
/ 05 февраля 2019

Как насчет объединения клавиш объекта с его значениями ?

function deepClone(o) {
    var keys = Object.keys(o);
    var values = Object.values(o);

    var clone = {};

    keys.forEach(function(key, i) {
        clone[key] = typeof values[i] == 'object' ? Object.create(values[i]) : values[i];
    });

    return clone;
}

Примечание: Этот метод не обязательно делает мелкие копии , но он копирует только с глубиной одного внутреннего объекта, что означает, что когда вам дается что-то вроде {a: {b: {c: null}}} он будет клонировать только те объекты, которые находятся непосредственно внутри них, поэтому технически deepClone(a.b).c является ссылкой на a.b.c, а deepClone(a).b является клоном, не является ссылкой .

0 голосов
/ 16 марта 2019

Keep It Super Simple (ПОЦЕЛУЙ):

Если есть object, он должен (в идеале) иметь constructor. Если у вас нет constructor для object; Я чувствую, вы должны создать constructor first .

ОК, теперь клонируем объекты:

function SampleObjectConstructor(config) {
    this.greet = config.greet;
}
// custom-object's prototype method
SampleObjectConstructor.prototype.showGreeting = function(){
  alert(this.greet);
}

var originalObject = new SampleObjectConstructor({greet: 'Hi!'});
var clonedObj = new SampleObjectConstructor(originalObject);

console.log(originalObject); // SampleObjectConstructor {greet: "Hi!"}
console.log('clonedObj : ', clonedObj) // SampleObjectConstructor {greet: "Hi!"}
console.log('cloned successfully?', originalObject !== clonedObj); // cloned successfully? true

Случай II: Если клонируемый объект не является custom object с его prototype methods; встроенный object constructor - Object может работать так же хорошо, т. е. new Object(originalObject) будет clone the original object для вас. В таком случае вам даже не нужно писать свой constructor.

var originalObject = {
    foo: 'bar'
}

var clonedObject = new Object(originalObject);

console.log(originalObject); // {foo: "bar"}
console.log(clonedObject); // {foo: "bar"}
console.log(originalObject !== clonedObject); // false

Удачи ...

0 голосов
/ 06 июня 2019

Вы можете использовать оператор Spread для клонирования объекта в JavaScript.

// оператор распространения, выполняющий работу concat

let arr = [1,2,3];  let arr2 = [4,5];  arr = [...arr,...arr2]; console.log(arr); 
0 голосов
/ 09 апреля 2016

Для моих целей самый элегантный способ создать новый объект из существующего (клон) - это использовать объектную функцию JavaScript 'assign'.

foo = {bar: 10, baz: {quox: 'batman'}};

clonedObject = Object.assign(foo);

clonedObject теперь является копией foo. Я не знаю деталей с точки зрения того, насколько хорошо это работает, или что такое «глубокая» копия, но я использую ее, чтобы также объединить атрибуты объекта с другими объектами. Кажется, работает для клонирования, а также.

...