停止从作为函数参数传递的对象的引用到新列表

时间:2016-02-23 21:14:25

标签: javascript angularjs

我不知道如何为此正确地写一个标题,因为我真的不知道发生了什么。

我正在尝试从数组中获取项目,并将其添加到新的对象列表中。 这很有效,但每当我修改项目(新列表中的那个)时,它也会在原始数组上进行更新/修改...... 这就像新项目和原项目之间仍有一些参考。

这就是问题所在。

我在这里复制问题,请查看Controller的评论并将其作为 整页 运行:

angular.module('app', [])
  .controller('MainCtrl', function($scope){
    
    $scope.items = [
      {id: 1, name: 'item 1'},
      {id: 2, name: 'item 2'},
      {id: 3, name: 'item 3'}
    ];
    
    $scope.newItems = {
      "helo": "World!"
    };
    
    //Add the selected item object to $scope.newItems
    $scope.addItem = function(item){
      $scope.newItems.item = item;
    };
    
    //Now add a color property to the previous added object
    $scope.addColor = function(clr){
      $scope.newItems.item.color = clr;
    };
    
    //We didn't touch $scope.items so far, yet the original object gets the same
    //modifications that I do to the same object on a different objects list.
    
    
    
    //just for testing purposes
    $scope.$watch('items', function(newValue, oldValue){
        if (newValue !== oldValue) {
          $scope.showProblem = true; //this should NEVER fire
        }
    }, true);
    
  });
<link data-require="bootstrap@3.3.5" data-semver="3.3.5" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
<script data-require="angularjs@1.4.9" data-semver="1.4.9" src="https://code.angularjs.org/1.4.9/angular.min.js"></script>

<body ng-app="app">
  <div ng-controller="MainCtrl">
    <div class="alert alert-danger" ng-if="showProblem">
      <strong>UNDESIRED BEHAVIOR:</strong> Original items array has been modified.
    </div>
    
    <ul class="list-group">
      <li ng-repeat="item in items track by item.id" class="list-group-item">
        {{item.name}}
        <a ng-click="addItem(item)" class="badge btn btn-sm btn-success" ng-if="!newItems.item">Add item</a>
        <a ng-click="addColor('red')" class="badge btn btn-sm btn-success" ng-if="newItems.item.id === item.id">Add color property</a>
      </li>
    </ul>
    
    <div class="panel panel-default">
      <div class="panel-body">
        <h3>Original item array</h3>
        <pre>{{items | json}}</pre>
      </div>
    </div>
    <div class="panel panel-default">
      <div class="panel-body">
        <h3>New item list</h3>
        <pre>{{newItems | json}}</pre>
      </div>
    </div>
  </div>
</body>

1 个答案:

答案 0 :(得分:2)

嗯 - 你完美地描述了这个问题 - 这是预期的行为!对象分配仅仅是引用。请看以下示例:

var obj = { color: "red" }
var obj2 = obj;

obj2.color = "black";
console.log(obj.color); //black;

objobj2都指向同一个对象 - 因此更新一个值会更新另一个。 Angular有一个内置的方法来处理这个问题,angular.copy(obj)将创建一个对象的副本,没有相同的引用:

$scope.newItems.item = angular.copy(item);