porque objetos em JavaScript são valores de referência, você não pode simplesmente copiar usando o =
. Mas não se preocupe, aqui estão 3 maneiras para você clonar um objeto 👍
# Objectos são Tipos de Referência
a Sua primeira pergunta pode ser, por que não posso usar =
. Vejamos o que acontece se fizermos isso:
const obj = { one: 1, two: 2 };const obj2 = obj;console.log( obj, // {one: 1, two: 2}; obj2, // {one: 1, two: 2};);
até agora, ambos os objetos parecem produzir a mesma coisa. Então, não há problema, certo?, Mas vamos ver o que acontece se editarmos o nosso segundo objecto:
const obj2.three = 3;console.log(obj2);// {one: 1, two: 2, three: 3}; <-- ✅console.log(obj);// {one: 1, two: 2, three: 3}; <-- 😱
WTH?! I changed obj2
but why was obj
also affected. Isso é porque os objectos são tipos de referência. Então quando você usa =
, copiou o ponteiro para o espaço de memória que ocupa. Os tipos de referência não possuem valores, eles são um ponteiro para o valor na memória.
Se você quiser saber mais sobre isso, confira O relógio Zhu De Gordon e o curso de código. É livre para registrar e assistir o vídeo “comparação com objetos”., Ele dá uma explicação fantástica sobre isso.
# 1. Usar o Spread
Usando o spread irá clonar o seu objecto. Note que esta será uma cópia rasa. A partir deste post, o operador de propagação para objetos de clonagem está na fase 4. Então, ainda não está oficialmente nas especificações. Então, se você fosse usar isso, você precisaria compilar com Babel (ou algo similar).
const food = { beef: '🥩', bacon: '🥓' };const cloneFood = { ...food };console.log(cloneFood);// { beef: '🥩', bacon: '🥓' }
# 2. A Usar O Objecto.atribuir
alternativamente, Object.assign
está no oficial lançado e também irá criar uma cópia rasa do objeto.,
const food = { beef: '🥩', bacon: '🥓' };const cloneFood = Object.assign({}, food);console.log(cloneFood);// { beef: '🥩', bacon: '🥓' }
Nota o vazio {}
como o primeiro argumento, isso irá garantir que você não modifica o objeto original 👍
# 3. Usando JSON
Esta forma final dar-lhe-á uma cópia profunda. Agora vou mencionar, esta é uma maneira rápida e suja de clonagem profunda de um objeto. Lodash Lodash
const food = { beef: '🥩', bacon: '🥓' };const cloneFood = JSON.parse(JSON.stringify(food));console.log(cloneFood);// { beef: '🥩', bacon: '🥓' }
# Lodash DeepClone vs JSON
Aqui está um comentário da comunidade. Sim, foi para o meu post anterior, Como clonar uma matriz profunda ., Mas a ideia ainda se aplica a objetos.Alfredo Salzillo: gostaria que você notasse que existem algumas diferenças entre deepClone e JSON.stringify / parse.
- JSON.o stringify / parse só funciona com o número e a cadeia de caracteres e o objeto literal sem propriedades de função ou símbolo.
- deepclone trabalha com todos os tipos, função e símbolo são copiados por referência.
Aqui está um exemplo:
@OlegVaraksin : o método JSON tem problemas com dependências circulares. Além disso, a ordem de Propriedades no objeto clonado pode ser diferente.,
# Clone superficial vs clone profundo
quando usei spread ...
para copiar um objecto, estou apenas a criar uma cópia superficial. Se a matriz for aninhada ou multidimensional, não funcionará. Aqui está o nosso exemplo, iremos utilizar:
const nestedObject = { flag: '🇨🇦', country: { city: 'vancouver', },};
# Cópia Superficial
Vamos clonar o nosso objeto de spread:
const shallowClone = { ...nestedObject };// Changed our cloned objectshallowClone.flag = '🇹🇼';shallowClone.country.city = 'taipei';
Então, nós mudamos o nosso objeto clonado por mudança de cidade. Vamos ver a saída.
console.log(shallowClone);// {country: '🇹🇼', {city: 'taipei'}}console.log(nestedObject);// {country: '🇨🇦', {city: 'taipei'}} <-- 😱
Uma cópia superficial significa que o primeiro nível é copiado, níveis mais profundos são referenciados.,
# Deep Copy
let’s take the same example but applying a deep copy using “JSON”
As you can see, the deep copy is a true copy for nested objects. Muitas vezes o time shallow copy é bom o suficiente, você realmente não precisa de uma cópia profunda. É como uma pistola de Pregos contra um martelo. A maior parte do tempo o martelo está perfeitamente bem. Usar uma pistola de pregos para algumas artes pequenas e artesanato é muitas vezes caso um exagero, um martelo é apenas bom. É tudo sobre usar a ferramenta certa para o trabalho certo 🤓
# desempenho
infelizmente, eu não posso escrever um teste para espalhar porque não está oficialmente no spec ainda., No entanto, eu incluí-o no teste para que você possa executá-lo no futuro😝. Mas o resultado mostra que Object.assign
é muito mais rápido que JSON
.
Performance Test
# Community Input
# Object.atribuir vs Spread
@d9el: é importante notar esse objecto.atribuir é uma função que modifica e retorna o objeto alvo. Em Samantha exemplo usando o seguinte,
const cloneFood = Object.assign({}, food);
{}
é o objeto é modificado., O objeto alvo não é referenciado por nenhuma variável nesse ponto, mas porque Object.assign
devolve o objeto alvo, somos capazes de armazenar o objeto atribuído resultante na variável
. Nós podemos mudar o nosso exemplo a seguir:
const food = { beef: '🌽', bacon: '🥓' };Object.assign(food, { beef: '🥩' });console.log(food);// { beef: '🥩', bacon: '🥓' }
Obviamente, o valor de beef
na nossa comida objeto é errado, para que possamos atribuir o correto valor de beef
uso de Object.assign
., Nós não estamos realmente usando o valor retornado da função em tudo, mas estamos modificando nosso objeto alvo que referenciamos com o const food
.
Spread on the other hand is an operator which copies properties of one object into a new object., Se quiséssemos replicar o exemplo acima usando espalhou para modificar a nossa variável food...
const food = { beef: '🌽', bacon: '🥓' };food = { ...food, beef: '🥩',};// TypeError: invalid assignment to const `food'
...
recebemos um erro, porque usamos a se espalhar quando a criação de novos objetos, e, portanto, a atribuição de um novo objeto para food
qual foi declarada com const
, o que é ilegal., Assim, podemos escolher para declarar uma nova variável para manter o nosso novo objeto, como o seguinte:
const food = { beef: '🌽', bacon: '🥓' };const newFood = { ...food, beef: '🥩',};console.log(newFood);// { beef: '🥩', bacon: '🥓' }
ou podemos declarar food
com let
ou var
o que nos permitiria atribuir um novo objeto:
let food = { beef: '🌽', bacon: '🥓' };food = { ...food, beef: '🥩',};console.log(food);// { beef: '🥩', bacon: '🥓' }
Obrigado: @d9el
# Clone Profundo utilizar Bibliotecas Externas
# Mais Maneiras usando JavaScript
- @hariharan_d3v :
Object.fromEntries(Object.entries(food))
clones do objeto.
Deixe uma resposta