Why and when to use angular.copy? (Deep Copy)
我一直将从服务接收到的所有数据直接保存到本地变量、控制器或作用域。我认为这是一个肤浅的复制品,对吗?
1 2 3 4 5 6 | Example: DataService.callFunction() .then(function(response) { $scope.example = response.data; }); |
最近有人告诉我使用angular.copy创建一个深度副本。
1 | $scope.example = angular.copy(response.data); |
然而,当我的角应用程序使用深拷贝信息时,它似乎以同样的方式工作。使用深度拷贝(angular.copy)有什么特别的好处,你能给我解释一下吗?
将对象或数组的值赋给另一个变量时,使用angular.copy,并且不应更改
如果不使用深度复制或angular.copy,则更改属性值或添加任何新属性将更新引用同一对象的所有对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | 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 |
1 2 3 4 | <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"> <button ng-click='printToConsole()'>Explain</button> |
在这种情况下,您不需要使用
说明:
= 表示一个引用,而angular.copy() 创建一个新对象作为深度复制。使用
= 意味着更改response.data 的属性将更改$scope.example 的相应属性,反之亦然。使用
angular.copy() ,两个对象将保持分离,并且变化不会相互反映。
我想说,在你的情况下,如果以后你不使用没有目的地的东西,你就没有必要使用。
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网站
我知道它已经回答了,但我只是想让它简单些。复制(数据),你可以在你想修改或改变你接收到的对象的情况下,通过保持其原始值不变。
例如:假设我已经调用了api并得到了originalobj,现在我想在某些情况下更改api originalobj的值,但是我也需要原始值,所以我可以做的是,在duplicateobj中复制我的api originalobj并修改duplicateobj,这样我的originalobj值就不会更改。简单来说,与JS对象的行为不同,DuplicateObj修改不会反映在OriginalObj中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | $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); |
结果就像……
1 2 3 4 5 6 7 8 9 | ----------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"} |
使用angular.copy时,将创建一个新对象并将其指定给目标(如果提供了目标),而不是更新引用。但还有更多。有一件很酷的事发生在深度复制之后。
假设您有一个工厂服务,它有更新工厂变量的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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; }]); |
以及使用此服务的控制器,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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); }]); |
当上述程序运行时,输出如下:
1 2 3 4 5 6 7 8 9 10 11 | ****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] |
因此,使用角度复制很酷的一点是,目标的引用会随着值的变化而反映出来,而不必再次手动重新分配值。
我只是在这里分享我的经验,我使用angular.copy()比较两个对象的属性。我正在处理一些没有表单元素的输入,我想知道如何比较两个对象的属性,并根据结果启用和禁用"保存"按钮。所以我用了如下。
我给我的虚拟对象分配了一个原始的服务器对象用户值,比如usercopy,并使用watch检查对用户对象的更改。
从服务器获取数据的服务器API
1 2 3 4 5 6 7 8 9 10 11 12 | 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(); }); |
//最初,由于对象相同,"保存"按钮被禁用,一旦发生更改,我将激活"保存"btn
1 2 3 4 5 6 7 8 9 10 11 12 13 | $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); |
我不确定,但对我来说,比较两个对象确实令人头晕目眩,但对angular.copy()来说,这是令人窒息的。
javascript传递变量
1 2 3 | var i = []; var j = i; i.push( 1 ); |
现在,由于
角度复制让我们失去这个参考,这意味着:
1 2 3 | var i = []; var j = angular.copy( i ); i.push( 1 ); |
这里的
在某些情况下,这种