O problema de cópia de objeto em JavaScript por referência ou por valor, que pode confundir muitos.
A regra em JavaScript, quando nos referimos a operação com objeto é a cópia por referência. No entanto, por vezes é necessário obtermos uma mera cópia.
Eis que o AngularJS tem suas próprias funções de manipulação de objetos. Iremos rapidamente tratar de duas. O copy e o extend.
O copy é muito importante entender, visto que cria um cópia do objeto alvo. O que faz possível duplicar o objeto. Já o extend é para cópia de propriedades de um objeto para outro. Importante se atentar que o mesmo cópia propriedades existente em um para o outro, mantendo intacta aquelas existentes somente no objeto receptor. Podemos verificar mais detalhes no exemplo abaixo:
#Primeiro objeto a = {"a":0,"b":1}; #Segundo objeto b = angular.copy(a); #Adiciona um atributo ao segundo objeto b.c = 2; #Nao interfere no primeiro objeto. Saída igual {"a":0,"b":1,"c":2}; console.log(b); #Nao foi alterada pela operacao no segundo objeto. Saída igual {"a":0,"b":1}; console.log(a); #Terceiro objeto c = {"d":3}; #Copia as propriedades existentes no primeiro objeto para o terceiro objeto angular.extend(c,a); #Nao interfere no primeiro objeto. Saída igual {"a":0,"b":1,"d":3}; console.log(c); #Nao foi alterada pela operacao no segundo objeto. Saída igual {"a":0,"b":1}; console.log(a);
No entanto, muito cuidado no uso do extend, visto que a sintaxe abaixo irá gerar um resultado de cópia por referência e não é seu uso correto. É justamente um erro de uso e que pode gerar problemas para encontrar o erro:
#Primeiro objeto a = {"a":0,"b":1}; #Segundo objeto b = angular.extend(a); #Adiciona um atributo ao segundo objeto b.c = 2; #Interfere no primeiro objeto. Saída igual {"a":0,"b":1,"c":2}; console.log(b); #Foi alterada pela operacao no segundo objeto. Saída igual {"a":0,"b":1,"c":2}; console.log(a);
Assim como o seguinte erro irá gerar comportamento não esperado
#Primeiro objeto a = {"a":0,"b":1}; #Segundo objeto b = {"d":3} #Irá sobreescrever b, visto que o método foi utilizado com a sintaxe errada. b = angular.extend(a); #Adiciona um atributo ao segundo objeto b.c = 2; #Interfere no primeiro objeto. Saída igual {"a":0,"b":1,"c":2}; console.log(b); #Foi alterada pela operacao no segundo objeto. Saída igual {"a":0,"b":1,"c":2}; console.log(a);