Porquê e quando usar angular.entendido? (Cópia Profunda)
Example:
DataService.callFunction()
.then(function(response) {
$scope.example = response.data;
});
Recentemente disseram-me para usar angular.copiar para criar uma cópia profunda.
$scope.example = angular.copy(response.data);
No entanto, a informação da cópia profunda parece estar a funcionar da mesma forma quando usada pela minha aplicação Angular. existem benefícios específicos para o uso de uma cópia profunda (angular.copiar) e você pode explicar para mim?
7 answers
Utilizar angular.copiar ao atribuir o valor do objecto ou da lista a outra variável e que object
o valor não deve ser alterado.
Sem cópia profunda ou usando angular.copiar , mudar o valor da propriedade ou adicionar qualquer nova propriedade actualizar todos os objectos a referenciarem esse mesmo objecto.
var app = angular.module('copyExample', []);
app.controller('ExampleController', ['$scope',
function($scope) {
$scope.printToConsole = function() {
$scope.main = {
first: 'first',
second: 'second'
};
$scope.child = angular.copy($scope.main);
console.log('Main object :');
console.log($scope.main);
console.log('Child object with angular.copy :');
console.log($scope.child);
$scope.child.first = 'last';
console.log('New Child object :')
console.log($scope.child);
console.log('Main object after child change and using angular.copy :');
console.log($scope.main);
console.log('Assing main object without copy and updating child');
$scope.child = $scope.main;
$scope.child.first = 'last';
console.log('Main object after update:');
console.log($scope.main);
console.log('Child object after update:');
console.log($scope.child);
}
}
]);
// Basic object assigning example
var main = {
first: 'first',
second: 'second'
};
var one = main; // same as main
var two = main; // same as main
console.log('main :' + JSON.stringify(main)); // All object are same
console.log('one :' + JSON.stringify(one)); // All object are same
console.log('two :' + JSON.stringify(two)); // All object are same
two = {
three: 'three'
}; // two changed but one and main remains same
console.log('main :' + JSON.stringify(main)); // one and main are same
console.log('one :' + JSON.stringify(one)); // one and main are same
console.log('two :' + JSON.stringify(two)); // two is changed
two = main; // same as main
two.first = 'last'; // change value of object's property so changed value of all object property
console.log('main :' + JSON.stringify(main)); // All object are same with new value
console.log('one :' + JSON.stringify(one)); // All object are same with new value
console.log('two :' + JSON.stringify(two)); // All object are same with new value
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="copyExample" ng-controller="ExampleController">
<button ng-click='printToConsole()'>Explain</button>
</div>
Nesse caso, não precisas de usar angular.copy()
Anotações :
=
representa uma referência enquantoangular.copy()
cria um novo objecto como uma cópia profunda.Usar
=
significaria que mudar uma propriedade deresponse.data
mudaria a propriedade correspondente de$scope.example
ou vice-versa.Usando
angular.copy()
os dois objectos permaneceriam separados e as alterações não se reflectiriam umas nas outras.
Eu diria {[[0]} que na sua situação é desnecessária se, mais tarde, você não usar é sem um destino angular.copy(source, [destination]);
.
Se for fornecido um destino, todos os seus elementos (para matrizes) ou as propriedades (para objectos) são apagadas e depois todas elementos / propriedades da fonte são copiados para ela.
Atribuí um valor de utilizador de um objecto original do servidor ao meu objecto fictício diz userCopy e usei o relógio para verificar as alterações no objecto do utilizador.
A minha API do servidor que me dá dados de servidorvar req = {
method: 'GET',
url: 'user/profile/'+id,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}
$http(req).success(function(data) {
$scope.user = data;
$scope.userCopy = angular.copy($scope.user);
$scope.btnSts=true;
}).error(function(data) {
$ionicLoading.hide();
});
/ / inicialmente o meu botão de gravação está desactivado porque os objectos são os mesmos, uma vez que algo / / muda estou a gravar o btn
$scope.btnSts=true;
$scope.$watch('user', function(newVal, oldVal){
console.log($scope.userCopy.name);
console.log();
if ($scope.userCopy.name !== $scope.user.name || $scope.userCopy.email !== $scope.user.email ) {
console.log('changed');
$scope.btnSts=false;
}else{
console.log('unchanged');
$scope.btnSts=true;
}
}, true);
Não tenho a certeza, mas comparar dois objectos foi sempre um erro para mim, mas com um ângulo.copy () it went smothly.
Quando se usa angular.copiar, em vez de atualizar a referência, um novo objeto é criado e atribuído ao destino(se um destino é fornecido). Mas há mais. Há uma coisa fixe que acontece depois de uma cópia profunda.
Digamos que você tem um serviço de fábrica que tem métodos que atualizam variáveis de fábrica.angular.module('test').factory('TestService', [function () {
var o = {
shallow: [0,1], // initial value(for demonstration)
deep: [0,2] // initial value(for demonstration)
};
o.shallowCopy = function () {
o.shallow = [1,2,3]
}
o.deepCopy = function () {
angular.copy([4,5,6], o.deep);
}
return o;
}]);
E um controlador que utilize este serviço,
angular.module('test').controller('Ctrl', ['TestService', function (TestService) {
var shallow = TestService.shallow;
var deep = TestService.deep;
console.log('****Printing initial values');
console.log(shallow);
console.log(deep);
TestService.shallowCopy();
TestService.deepCopy();
console.log('****Printing values after service method execution');
console.log(shallow);
console.log(deep);
console.log('****Printing service variables directly');
console.log(TestService.shallow);
console.log(TestService.deep);
}]);
Quando o programa acima for executado, a saída será a seguinte,
****Printing initial values
[0,1]
[0,2]
****Printing values after service method execution
[0,1]
[4,5,6]
****Printing service variables directly
[1,2,3]
[4,5,6]
Assim o fresco a coisa sobre o uso de cópia angular é que, as referências do destino são refletidas com a mudança de valores, sem ter que re-atribuir os valores manualmente, novamente.
Por exemplo: suponha que eu tenha feito a chamada de api e tenho o meu originalObj, agora eu quero mudar os valores da api originalObj para alguns casos, mas eu quero que os valores originais também, então o que eu posso fazer é, eu posso fazer uma cópia de um api originalObj em duplicateObj e modificar o duplicateObj desta forma meus valores originais não mudarão. Em palavras simples, a modificação duplicateObj não irá refletir no originalObj ao contrário de como o JS obj se comporta.
$scope.originalObj={
fname:'sudarshan',
country:'India'
}
$scope.duplicateObj=angular.copy($scope.originalObj);
console.log('----------originalObj--------------');
console.log($scope.originalObj);
console.log('-----------duplicateObj---------------');
console.log($scope.duplicateObj);
$scope.duplicateObj.fname='SUD';
$scope.duplicateObj.country='USA';
console.log('---------After update-------')
console.log('----------originalObj--------------');
console.log($scope.originalObj);
console.log('-----------duplicateObj---------------');
console.log($scope.duplicateObj);
O resultado é como....
----------originalObj--------------
manageProfileController.js:1183 {fname: "sudarshan", country: "India"}
manageProfileController.js:1184 -----------duplicateObj---------------
manageProfileController.js:1185 {fname: "sudarshan", country: "India"}
manageProfileController.js:1189 ---------After update-------
manageProfileController.js:1190 ----------originalObj--------------
manageProfileController.js:1191 {fname: "sudarshan", country: "India"}
manageProfileController.js:1192 -----------duplicateObj---------------
manageProfileController.js:1193 {fname: "SUD", country: "USA"}
Javascript passa variáveis by reference
, isto significa que:
var i = [];
var j = i;
i.push( 1 );
Agora por causa de by reference
a parte i
é[1], e j
também é[1], embora apenas i
tenha sido alterada. Isto porque quando dizemos j = i
o javascript não copia a variável i
e atribui-a a j
mas as referências i
a variável j
.
A cópia Angular deixa-nos perder esta referência, o que significa:
var i = [];
var j = angular.copy( i );
i.push( 1 );
Agora i
aqui é igual a[1], enquanto j
ainda é igual a [].
Existem situações em que este tipo de funcionalidade copy
é muito útil.