Qual é a forma mais eficiente de clonar um objeto JavaScript? I'vi obj = eval(uneval(o)));
sendo utilizado, mas that's non-standard and only supported by Firefox.
I'fiz coisas como obj = JSON.parse(JSON.stringify(o));
mas questiona a eficiência.
I'também já vi funções de cópia recursivas com várias falhas.
I'estou surpreso que não exista uma solução canônica.
It's chamado "clonagem estruturada", funciona experimentalmente no Nó 11 e mais tarde, e esperamos que aterrisse em navegadores. Veja esta resposta para mais detalhes.
Se você não utiliza Date
s, funções, undefined
, Infinity
, RegExps, Maps, Sets, Blobs, FileLists, ImageDatas, Arrays esparsas, Typed Arrays ou outros tipos complexos dentro do seu objeto, um liner muito simples para clonar profundamente um objeto é:
JSON.parse(JSON.stringify(object))
const a = {
string: 'string',
number: 123,
bool: false,
nul: null,
date: new Date(), // stringified
undef: undefined, // lost
inf: Infinity, // forced to 'null'
re: /.*/, // lost
}
console.log(a);
console.log(typeof a.date); // Date object
const clone = JSON.parse(JSON.stringify(a));
console.log(clone);
console.log(typeof clone.date); // result of .toISOString()
Ver Corban's answer para benchmarks.
Como a clonagem de objetos não é trivial (tipos complexos, referências circulares, função, etc.), a maioria das bibliotecas principais fornece função para clonar objetos. **Don't reinvente a roda*** - se você'já está usando uma biblioteca, verifique se ela tem uma função de clonagem de objetos. Por exemplo, se já está usando uma biblioteca, verifique se ela tem uma função de clonagem de objetos,
cloneDeep
; pode ser importado separadamente através do módulo lodash.clonedeep e é provavelmente a sua melhor escolha se você'ainda não está utilizando uma biblioteca que fornece uma função de clonagem profundaangular.copy
jQuery.extend(true, { }, oldObject)
; .clone()
apenas clones elementos DOMPara completar, note que o ES6 oferece dois mecanismos de cópia rasa: Object.assign()` e o operador de propagação.
Se houvesse' não havia nenhum construído, você poderia tentar:
function clone(obj) {
if (obj === null || typeof (obj) !== 'object' || 'isActiveClone' in obj)
return obj;
if (obj instanceof Date)
var temp = new obj.constructor(); //or new Date(obj);
else
var temp = obj.constructor();
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
obj['isActiveClone'] = null;
temp[key] = clone(obj[key]);
delete obj['isActiveClone'];
}
}
return temp;
}