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

时间:2015-10-09 17:16:45

标签: javascript angularjs deep-copy shallow-copy

我一直在将从服务收到的所有数据直接保存到本地变量,控制器或范围。我认为它会被认为是浅层副本,这是正确的吗?

Example:

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

最近我被告知要使用angular.copy来创建深层副本。

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

然而,当我的Angular应用程序使用时,深层复制信息似乎以相同的方式工作。 使用深层副本(angular.copy)是否有特定的好处,请您向我解释一下?

6 个答案:

答案 0 :(得分:41)

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

解释

  • =表示引用,而angular.copy()创建新对象作为深层副本。

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

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

答案 1 :(得分:7)

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

  

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

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

答案 2 :(得分:1)

我只是在这里分享我的经验,我使用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();
            });

//最初我的保存按钮被禁用,因为对象是相同的,一旦//更改我正在活动保存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);

我不确定但是比较两个对象总是对我来说总是如此,但是使用angular.copy()它会变得很光滑。

答案 3 :(得分:1)

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

假设您有一个工厂服务,其中包含更新工厂变量的方法。

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]

因此,使用角度复制的一个很酷的事情是,目标的引用会反映为值的更改,而不必再次手动重新分配值。

答案 4 :(得分:1)

我知道它已经回答了,我仍然只是想让它变得简单。 因此,如果您希望通过保持原始值未修改/未更改来修改/更改接收到的对象,则可以使用angular.copy(数据)。

例如:假设我已经进行了api调用并获得了我的originalObj,现在我想在某些情况下更改api originalObj的值,但我想要原始值,所以我能做的就是,我可以在duplicateObj中复制我的api originalObj并修改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"}

答案 5 :(得分:-2)

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变量。

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

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

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

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