Porquê e quando usar angular.entendido? (Cópia Profunda)

Tenho guardado todos os dados recebidos dos serviços directamente para variável local, controlador ou âmbito. O que suponho que seria considerado uma cópia superficial, correcto?

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?

Author: Superman2971, 2015-10-09

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>
 141
Author: Sarjan Desai, 2017-12-07 00:38:18

Nesse caso, não precisas de usar angular.copy()

Anotações :

  • = representa uma referência enquanto angular.copy() cria um novo objecto como uma cópia profunda.

  • Usar = significaria que mudar uma propriedade de response.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.

 36
Author: Nicolas2bert, 2016-08-25 06:00:32

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.

Https://docs.angularjs.org/api/ng/function/angular.copy

 7
Author: Esko, 2015-10-09 17:34:37
Estou apenas a partilhar a minha experiência aqui, usei o angular.copy () for comparing two objects properties. Eu estava trabalhando em uma série de entradas sem elemento de forma, eu estava me perguntando como comparar duas propriedades de objetos e com base no resultado que eu tenho que ativar e desativar o botão Salvar. Então eu usei como abaixo.

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 servidor
var 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.
 1
Author: Sudarshan Kalebere, 2016-08-31 14:24:16

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.

 1
Author: Pubudu Dodangoda, 2016-12-11 13:44:46
[[3] eu sei que ele já respondeu, Ainda assim eu estou apenas tentando torná-lo simples. Tão angular.copiar (dados) você pode usar no caso em que deseja modificar/alterar o seu objecto recebido mantendo os seus valores originais não modificados/inalterados.

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"}
 1
Author: Sudarshan Kalebere, 2018-01-16 06:38:33

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.

 -2
Author: guramidev, 2015-10-09 17:40:01