为什么我需要在工厂使用angular.copy?

时间:2015-02-07 05:25:42

标签: javascript angularjs

我正在尝试让Thing工厂发出HTTP请求,并能够在我的控制器中使用响应。

  1. 在我的工厂,我必须angular.copy(data, arr)。简单地做arr = data不起作用。为什么是这样? angular.copy()只需a)从arr删除所有内容,然后按b)迭代data并将内容分配给arr。它与arr = data之间的唯一区别是arr指向data而不是data的新副本。这为什么重要?为什么arr = data.slice(0)不起作用(根据我的理解,它与angular.copy)几乎相同?

  2. 实现目标的最佳方法是什么? (正确使用工厂)

  3. main.html中

    <div class="container">
    
    <div class="page-header">
      <h1>Test App</h1>
    </div>
    
    <ul>
      <li ng-repeat="thing in things">{{thing.name}}</li>
    </ul>
    
    </div>
    

    main.controller.js

    'use strict';
    
    angular.module('testApp')
      .factory('Thing', function($http) {
        var arr = [];
        return {
          things: arr,
          get: function() {
            $http.get('/api/things').success(function(data) {
              angular.copy(data, arr); // this works
              // arr = data; but this doesn't
              // arr = data.slice(0); and neither does this
    
            });
          }
        };
      })
      .controller('MainCtrl', function ($scope, Thing) {
        Thing.get();
        $scope.things = Thing.things;
      });
    

2 个答案:

答案 0 :(得分:7)

您的问题与角度有关,但与Javascript无关。

var arr = [] // arr is a pointer to an empty array
var things = arr  // things is a pointer to the same empty array
arr = data   // now arr points to data, but things still points to the empty array

您可以通过运行以下代码来说服自己:

var a = [1];
var b = a;
a = [2];
// Now if you console.log a and b, a === [2] and b === [1]

但是,如果您操纵对象的属性

var a = { data: 1 }
var b = a;
a.data = 2;
// Now a.data and b.data are the same: 2
a = { data: 3 };
// Here we changed a, not its property, so a and b are not the same anymore
// a.data === 3 but b.data === 2

如果您了解这一点,有很多方法可以解决您的问题,例如:

angular.module('testApp')
  .factory('Thing', function($http) {
  var obj = {};
  return {
    things: obj,
    get: function() {
      $http.get('/api/things').success(function(data) {
        obj.data = data;
      });
    }
  };
})

在您的HTML中使用things.data

或者,如果您不想使用对象属性,而是直接使用数组,而不是替换指针,则只需更新数组的内容(因此arr仍然指向同一个数组): / p>

angular.module('testApp')
  .factory('Thing', function($http) {
  var arr= [];
  return {
    things: arr,
    get: function() {
      $http.get('/api/things').success(function(data) {
        for (var i in data) {
          arr[i] = data[i];
        }
      });
    }
  };
})

答案 1 :(得分:0)

这是因为您将arr设置为某个新的数组实例而不是使用当前实例。这是你正在做的事情的类比:

var foo = function() {
    this.test = 'hello';
    console.log(this.test);
};

foo = function() {
    this.test = 'other';
    console.log(this.test);
};

console.log(foo()); // outputs other

angular.copy反而做了类似的事情:

// foreach item in the source (in this case data)
arr.push({
   my: "value"
});