Почему и когда использовать angular.копия? (глубокое копирование)

Я сохраняю все данные, полученные от служб, непосредственно в локальную переменную, контроллер или область. То, что я полагаю, будет считаться мелкой копией, верно?

Example:

DataService.callFunction()
.then(function(response) {
  $scope.example = response.data;
});

недавно мне сказали использовать angular.копировать для создания глубокой копии.

$scope.example = angular.copy(response.data);

однако информация о глубокой копии, похоже, работает таким же образом при использовании моего углового приложения. существуют ли конкретные преимущества использования глубокой копии (угловой.копировать) и можете ли вы пожалуйста, объясните мне?

7 ответов


использовать угловое.копия при присвоении значения объекта или массива другой переменной и что object значение не должно быть изменено.

без глубокая копия или через угловое.копия, изменение значения свойства или добавление любого нового свойства "обновить все" объекта ссылки на тот же объект.

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>

в этом случае вам не нужно использовать angular.copy()

объяснение :

  • = представляет ссылку, а angular.copy() создает новый объект в виде глубокой копии.

  • используя = означало бы, что изменение свойства response.data изменить соответствующее свойство $scope.example или наоборот.

  • используя angular.copy() два объекта останутся отдельными, и изменения будут не размышлять друг о друге.


Я бы сказал angular.copy(source); в вашей ситуации нет необходимости, если позже вы не используете его без назначения angular.copy(source, [destination]);.

Если пункт назначения указан, все его элементы (для массивов) или свойства (для объектов) удаляются, а затем все элементы / свойства из источника копируются в него.

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


Я просто делюсь своим опытом здесь, я использовал угловой.копия() для сравнения двух свойств объектов. Я работал над рядом входов без элемента формы, мне было интересно, как сравнить свойства двух объектов и на основе результата я должен включить и отключить кнопку сохранения. Так что я использовал ниже.

Я назначил исходные пользовательские значения объекта сервера моему фиктивному объекту, скажем userCopy, и использовал watch для проверки изменений объекта пользователя.

мой сервер API, который получает меня данные с сервера

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();
            });

/ / первоначально моя кнопка сохранения отключена, потому что объекты одинаковы, как только что-то / / изменения я активирую save 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);

Я не уверен, но сравнение двух объектов было действительно headche для меня всегда, но с угловым.копия() его пошел smothly.


при использовании угловых.копирование вместо обновления ссылки создается новый объект, который назначается назначению (если назначение указано). Но это еще не все. Есть одна классная вещь, которая происходит после глубокой копии.

скажем, у вас есть заводская служба, которая имеет методы, которые обновляют заводские переменные.

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;
}]);

и контроллер, который использует эту услугу,

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);
}]);

когда вышеуказанная программа бежится выход будет как следует,

****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]

таким образом, классная вещь об использовании угловой копии заключается в том, что ссылки назначения отражаются с изменением значений, без необходимости повторно назначать значения вручную, снова.


Я знаю, что уже ответили, но я просто пытаюсь сделать его простым. Такой угловатый.копировать(данные) вы можете использовать в случае, если вы хотите изменить/изменить полученный объект, сохранив его исходные значения неизмененными.

например: предположим я сделал вызов API и у меня originalObj, теперь я хочу изменить значения API-интерфейс originalObj для какого-то дела, но я хочу, чтобы исходные значения слишком что я могу сделать, я могу сделать копию моих API originalObj в duplicateObj и изменить duplicateObj таким образом мои значения originalObj не изменится. Говоря простыми словами, модификация duplicateObj не будет отражать в originalObj в отличие от поведения JS obj.

 $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);

результат понравился....

    ----------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 передает переменные by reference, это означает, что:

var i = [];
var j = i;
i.push( 1 );

из-за by reference часть i есть [1], и j также [1], хотя только i был изменен. Это потому, что когда мы говорим j = i javascript не копирует i переменная и назначьте ее j но ссылок i переменную через j.

Угловое копирование позволяет нам потерять эту ссылку, что означает:

var i = [];
var j = angular.copy( i );
i.push( 1 );

теперь i здесь равна в [1], в то время как j все равно [].

бывают ситуации, когда такой вид copy функциональность очень удобно.