Então eu estava brincando outro dia apenas para ver exatamente como a atribuição em massa funciona em JavaScript.
Primeiro tentei este exemplo no console:
a = b = {};
a.foo = 'bar';
console.log(b.foo);
O resultado foi "bar" sendo exibido em um alerta. Isso é bastante justo a
e , na b
verdade , são apenas apelidos para o mesmo objeto. Então eu pensei, como eu poderia tornar este exemplo mais simples.
a = b = 'foo';
a = 'bar';
console.log(b);
É praticamente a mesma coisa, não é? Bem, desta vez, ele foo
não retorna bar
como eu esperava do comportamento do primeiro exemplo.
Por que isso acontece?
NB Este exemplo pode ser simplificado ainda mais com o seguinte código:
a = {};
b = a;
a.foo = 'bar';
console.log(b.foo);
a = 'foo';
b = a;
a = 'bar';
console.log(b);
(Suspeito que o JavaScript trata primitivos como strings e inteiros de maneira diferente para hashes. Os hashes retornam um ponteiro, enquanto os primitivos "principais" retornam uma cópia de si mesmos)
fonte
Respostas:
No primeiro exemplo, você está definindo uma propriedade de um objeto existente. No segundo exemplo, você está atribuindo um novo objeto.
a
eb
agora são ponteiros para o mesmo objeto. Então, quando você faz:Estabelece
b.foo
também desdea
eb
apontam para o mesmo objeto.Contudo!
Se você fizer isso:
você está dizendo que agora
a
aponta para um objeto diferente. Isso não tem efeito sobre o que foia
apontado antes.Em JavaScript, atribuir uma variável e atribuir uma propriedade são 2 operações diferentes. É melhor pensar em variáveis como ponteiros para objetos, e quando você atribui diretamente a uma variável, você não está modificando nenhum objeto, apenas repondo sua variável para um objeto diferente.
Mas atribuir uma propriedade, como
a.foo
, modificará o objeto para o quala
aponta. Isso, é claro, também modifica todas as outras referências que apontam para esse objeto simplesmente porque todas apontam para o mesmo objeto.fonte
var foo = new String('foo');
, então seria um objeto string (e irá confirmar isso). Mas se você declarar por meio de um literal de string, então eles são primitivos de string. Veja: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…typeof
Sua pergunta já foi satisfatoriamente respondida por Squeegy - ela não tem nada a ver com objetos vs. primitivos, mas com reatribuição de variáveis vs. propriedades de configuração no mesmo objeto referenciado.
Parece haver muita confusão sobre os tipos de JavaScript nas respostas e comentários, então aqui está uma pequena introdução ao sistema de tipos do JavaScript:
Em JavaScript, existem dois tipos fundamentalmente diferentes de valores: primitivos e objetos (e não existe nada como um 'hash').
Cordas, números e booleanos, bem como
null
eundefined
são primitivos, os objetos são tudo o que pode ter propriedades. Mesmo matrizes e funções são objetos regulares e, portanto, podem conter propriedades arbitrárias. Eles apenas diferem na propriedade interna [[Class]] (funções adicionalmente têm uma propriedade chamada [[Call]] e [[Construct]], mas ei, isso são detalhes).A razão pela qual os valores primitivos podem se comportar como objetos é o autoboxing, mas os próprios primitivos não podem conter nenhuma propriedade.
Aqui está um exemplo:
Isso resultará em
undefined
:a
contém um valor primitivo, que é promovido a um objeto ao atribuir a propriedadefoo
. Mas esse novo objeto é imediatamente descartado, então o valor defoo
é perdido.Pense assim:
fonte
Você está mais ou menos correto, exceto que o que está se referindo como um "hash" é, na verdade, apenas uma sintaxe abreviada para um objeto.
No primeiro exemplo, um e b referem-se ambos ao mesmo objecto. No segundo exemplo, você altera a para se referir a outra coisa.
fonte
aqui está minha versão da resposta:
fonte
Você está definindo a para apontar para um novo objeto string, enquanto b continua apontando para o objeto string antigo.
fonte
No primeiro caso você altera alguma propriedade do objeto contido na variável, no segundo caso você atribui um novo valor à variável. Isso são coisas fundamentalmente diferentes. As variáveis
a
eb
não são de alguma forma magicamente ligadas pela primeira atribuição, elas apenas contêm o mesmo objeto. Esse também é o caso no segundo exemplo, até que você atribua um novo valor àb
variável.fonte
A diferença é entre tipos e objetos simples.
Qualquer coisa que seja um objeto (como um array ou uma função) é passado por referência.
Qualquer coisa que seja um tipo simples (como uma string ou um número) é copiado.
Sempre tenho uma função copyArray à mão, então posso ter certeza de que não estou criando um monte de aliases para o mesmo array.
fonte