Javascript 为什么以及何时使用 angular.copy?(深拷贝)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33043850/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 14:33:56  来源:igfitidea点击:

Why and when to use angular.copy? (Deep Copy)

javascriptangularjsdeep-copyshallow-copy

提问by Superman2971

I've been saving all the data received from services direct to local variable, controller, or scope. What I suppose would be considered a shallow copy, is that correct?

我一直在将从服务接收到的所有数据直接保存到局部变量、控制器或作用域。我想什么会被认为是浅拷贝,对吗?

Example:

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

Recently I was told to use angular.copy in order to create a deep copy.

最近有人告诉我使用 angular.copy 来创建一个深拷贝。

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

However, the deep copy information seems to be working in the same way when used by my Angular application. Are there specific benefits to using a deep copy (angular.copy) and can you please explain them to me?

但是,深拷贝信息在我的 Angular 应用程序使用时似乎以相同的方式工作。使用深拷贝(angular.copy)有什么特别的好处,你能向我解释一下吗?

回答by Sarjan Desai

Use angular.copywhen assigning value of object or array to another variable and that objectvalue should not be changed.

将对象或数组的值分配给另一个变量时使用angular.copy并且object不应更改该值。

Without deep copyor using angular.copy, changing value of property or adding any new property update all objectreferencing that same object.

在没有深度复制或使用angular.copy 的情况下,更改属性值或添加任何新属性会更新引用同一对象的所有对象。

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>

回答by Nicolas2bert

In that case, you don't need to use angular.copy()

在这种情况下,您不需要使用 angular.copy()

Explanation:

说明

  • =represents a reference whereas angular.copy()creates a new object as a deep copy.

  • Using =would mean that changing a property of response.datawould change the corresponding property of $scope.exampleor vice versa.

  • Using angular.copy()the two objects would remain seperate and changes would not reflect on each other.

  • =代表一个引用,而angular.copy()创建一个新对象作为深拷贝。

  • 使用=意味着改变 的属性response.data会改变相应的属性,$scope.example反之亦然。

  • 使用angular.copy()这两个对象将保持独立,更改不会相互反映。

回答by Esko

I would say angular.copy(source);in your situation is unnecessary if later on you do not use is it without a destination angular.copy(source, [destination]);.

我会说angular.copy(source);在你的情况下是不必要的,如果以后你不使用它没有目的地angular.copy(source, [destination]);

If a destination is provided, all of its elements (for arrays) or properties (for objects) are deleted and then all elements/properties from the source are copied to it.

如果提供了目标,则删除其所有元素(对于数组)或属性(对于对象),然后将源中的所有元素/属性复制到该目标。

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

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

回答by Sudarshan Kalebere

I am just sharing my experience here, I used angular.copy() for comparing two objects properties. I was working on a number of inputs without form element, I was wondering how to compare two objects properties and based on result I have to enable and disable the save button. So I used as below.

我只是在这里分享我的经验,我使用 angular.copy() 来比较两个对象的属性。我正在处理许多没有表单元素的输入,我想知道如何比较两个对象的属性,并根据结果我必须启用和禁用保存按钮。所以我使用如下。

I assigned an original server object user values to my dummy object to say userCopy and used watch to check changes to the user object.

我将一个原始服务器对象用户值分配给我的虚拟对象说 userCopy 并使用 watch 来检查对用户对象的更改。

My server API which gets me data from the server:

我的服务器 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();
});

//initially my save button is disabled because objects are same, once something 
//changes I am activating save button

$scope.btnSts = true;
$scope.$watch('user', function(newVal, oldVal) {
    console.log($scope.userCopy.name);

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

I am not sure but comparing two objects was really headache for me always but with angular.copy() it went smoothly.

我不确定,但比较两个对象对我来说总是很头疼,但是使用 angular.copy() 却很顺利。

回答by Pubudu Dodangoda

When using angular.copy, instead of updating the reference, a new object is created and assigned to the destination(if a destination is provided). But there's more. There's this cool thing that happens after a deep copy.

使用 angular.copy 时,不是更新引用,而是创建一个新对象并将其分配给目标(如果提供了目标)。但还有更多。在深度复制之后发生了一件很酷的事情。

Say you have a factory service which has methods which updates factory variables.

假设您有一个工厂服务,它具有更新工厂变量的方法。

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

and a controller which uses this service,

和使用此服务的控制器,

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

When the above program is run the output will be as follows,

当上面的程序运行时,输出将如下所示,

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

Thus the cool thing about using angular copy is that, the references of the destination are reflected with the change of values, without having to re-assign the values manually, again.

因此,使用 angular copy 的好处在于,目标的引用会随着值的变化而反映,而无需再次手动重新分配值。

回答by Sudarshan Kalebere

I know its already answered, still i am just trying to make it simple. So angular.copy(data) you can use in case where you want to modify/change your received object by keeping its original values unmodified/unchanged.

我知道它已经回答了,我仍然只是想让它变得简单。所以 angular.copy(data) 你可以在你想通过保持其原始值不变/不变来修改/更改接收到的对象的情况下使用。

For example:suppose i have made api call and got my originalObj, now i want to change the values of api originalObj for some case but i want the original values too so what i can do is, i can make a copy of my api originalObj in duplicateObj and modify duplicateObj this way my originalObj values will not change. In simple words duplicateObj modification will not reflect in originalObj unlike how js obj behave.

例如:假设我已经进行了 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);

Result is like....

结果就像……

    ----------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"}

回答by guramidev

Javascript passes variables by reference, this means that:

Javascript 传递变量by reference,这意味着:

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

Now because of by referencepart iis [1], and jis [1] as well, even though only iwas changed. This is because when we say j = ijavascript doesn't copy the ivariable and assign it to jbut references ivariable through j.

现在因为by reference部分i是 [1],并且j也是 [1],即使只是i被改变了。这是因为当我们说j = ijavascript 不会复制i变量并将其分配给它时,j而是i通过j.

Angular copy lets us lose this reference, which means:

Angular 副本让我们失去了这个引用,这意味着:

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

Now ihere equals to [1], while jstill equals to [].

现在i这里等于[1],而j仍然等于[]。

There are situations when such kind of copyfunctionality is very handy.

在某些情况下,这种copy功能非常方便。