Ao passar objetos como parâmetros, o JavaScript os passa por referência e torna difícil criar cópias locais dos objetos.
var o = {}; (function(x){ var obj = x; obj.foo = 'foo'; obj.bar = 'bar'; })(o)
o
terá.foo
e.bar
.É possível contornar isso clonando; exemplo simples:
var o = {}; function Clone(x) { for(p in x) this[p] = (typeof(x[p]) == 'object')? new Clone(x[p]) : x[p]; } (function(x){ var obj = new Clone(x); obj.foo = 'foo'; obj.bar = 'bar'; })(o)
o
não terá.foo
ou.bar
.
Questão
- Existe uma maneira melhor de passar objetos por valor, além de criar uma cópia / clone local?
javascript
Vol7ron
fonte
fonte
Respostas:
Na verdade não.
Dependendo do que você realmente precisa, uma possibilidade pode ser definir
o
como o protótipo de um novo objeto.Portanto, quaisquer propriedades adicionadas
obj
não serão adicionadaso
. Todas as propriedades adicionadasobj
com o mesmo nome de propriedade de uma propriedade emo
irão sombrear ao
propriedade.Obviamente, todas as propriedades adicionadas a
o
estarão disponíveisobj
se não estiverem sombreadas, e todos os objetos que estãoo
na cadeia de protótipos verão as mesmas atualizações emo
.Além disso, se
obj
tem uma propriedade que faz referência a outro objeto, como um Array, você precisará ter certeza de sombrear esse objeto antes de adicionar membros ao objeto, caso contrário, esses membros serão adicionadosobj
e serão compartilhados entre todos os objetos que temobj
na cadeia de protótipos.Aqui você pode ver que porque você não sombra da matriz em
baz
ono
com umabaz
propriedade emobj
, ao.baz
matriz é modificado.Então, em vez disso, você precisa sombrear primeiro:
fonte
Object.create
na minha resposta também, mas não quis me esticar para explicar a superficialidade da cópia ;-)var obj = new Object(x)
. Para mim, eu acho quenew Object(x)
teria um desempenhoObject.create(x)
padrão - interessantenew Object(x)
apenas cospe de volta o mesmo objeto (como você provavelmente percebeu) . Seria bom se houvesse uma maneira nativa de clonar. Não tenho certeza se há algo em andamento.Confira esta resposta https://stackoverflow.com/a/5344074/746491 .
Resumindo,
JSON.parse(JSON.stringify(obj))
é uma maneira rápida de copiar seus objetos, se seus objetos puderem ser serializados para json.fonte
JSON
não está incluído e precisa ser definido - pode muito bem ser mais descritivo com um nome comoClone
. No entanto, suspeito que minha opinião pode mudar no futuro, uma vez que JSON é mais fortemente integrado em software não baseado em navegador, como bancos de dados e IDEsAqui está a função de clone que realizará uma cópia profunda do objeto:
Agora você pode usar assim:
fonte
Usar
Object.assign()
Exemplo:
Um exemplo mais limpo que faz a mesma coisa:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
fonte
var b = Object.assign({}, a);
a
será copiado como referência.Você está um pouco confuso sobre como os objetos funcionam em JavaScript. A referência do objeto é o valor da variável. Não há valor não serializado. Quando você cria um objeto, sua estrutura é armazenada na memória e a variável à qual foi atribuída contém uma referência a essa estrutura.
Mesmo se o que você está pedindo foi fornecido em algum tipo de construção de linguagem nativa fácil, ainda seria tecnicamente uma clonagem.
JavaScript é realmente apenas passado por valor ... é apenas que o valor passado pode ser uma referência a algo.
fonte
Usa isto
x
ex1
serão dois objetos diferentes, a mudançax
não mudaráx1
fonte
Javascript sempre passa por valor. Neste caso está passando uma cópia da referência
o
para a função anônima. O código está usando uma cópia da referência, mas está alterando o único objeto. Não há como fazer o javascript passar por qualquer coisa que não seja valor.Neste caso, o que você deseja é passar uma cópia do objeto subjacente. Clonar o objeto é o único recurso. Seu método de clone precisa de uma pequena atualização embora
fonte
Como consideração aos usuários do jQuery, também há uma maneira de fazer isso de maneira simples usando o framework. Apenas outra maneira que o jQuery torna nossas vidas um pouco mais fáceis.
referências :
fonte
Na verdade, Javascript é sempre passado por valor . Mas porque as referências de objeto são valores , os objetos se comportarão como se fossem passados por referência .
Portanto, para contornar isso, stringifique o objeto e analise -o de volta, ambos usando JSON. Veja o exemplo de código abaixo:
fonte
use obj2 = {... obj1} Agora, ambos os objetos têm o mesmo valor e referências diferentes
fonte
let a = {value: "old"}
let b = [...a]
b.value = "new"
, e a será{value: "old"}
, b será{value: "new"}
. Mas não funciona quandolet a = [{value: "old"}]
let b = [...a]
b[0].value = "new"
, e a será[{value: "new"}]
, b será[{value: "new"}]
.Eu precisava copiar um objeto por valor (não por referência) e achei esta página útil:
Qual é a maneira mais eficiente de clonar profundamente um objeto em JavaScript? . Em particular, clonar um objeto com o seguinte código de John Resig:
fonte
Com a sintaxe ES6:
let obj = Object.assign({}, o);
fonte
Object.assign
é que ele não executa uma cópia profunda.No final das contas, é apenas um proxy extravagante e excessivamente complicado, mas talvez Catch-All Proxies pudesse fazer isso?
fonte
Se você estiver usando Lodash ou
npm
, use a função de mesclagem de Lodash para copiar em profundidade todas as propriedades do objeto para um novo objeto vazio como:var objectCopy = lodash.merge({}, originalObject);
https://lodash.com/docs#merge
https://www.npmjs.com/package/lodash.merge
fonte