2014-01-11 279 views
2

我已經證明了我的問題在小提琴:http://jsfiddle.net/sljux/zVg7R/3/計算總和

我有對象的數組。爲簡單起見,可以說每個對象都有一個名稱,值的陣列,所有觀察到的:

self.array = [ 
    { 
     name: ko.observable("first"), 
     values: ko.observableArray([1, 2, 3]) 
    }, 
    { 
     name: ko.observable("second"), 
     values: ko.observableArray([2, 3, 4]) 
    }, 
    { 
     name: ko.observable("third"), 
     values: ko.observableArray([3, 4, 5]) 
    } 
]; 

從那個陣列I需要過濾掉某些對象,並增加一個額外的計算以每一個,其計算所述所有值的總和。過濾部分對問題並不重要,所以不會完成。的問題是,可觀察到的需要是每個對象的屬性,並且它需要引用該對象的values陣列。

我最好的嘗試是:

self.newArray = ko.observableArray([]); 

for(var i = 0; i < self.array.length; i++) { 
    var obj = { 
     name: ko.observable("new " + self.array[i].name()), 
     values: ko.observableArray(self.array[i].values()) 
    }; 

    obj.sum = ko.computed({ 
     read: function() { 
      var res = 0; 

      for (var j = 0; j < obj.values().length; j++) 
       res += obj.values()[j]; 

      return res; 
     }, 
     owner: obj 
    }); 

    self.newArray.push(obj); 
} 

的問題是,參照values觀察到的數組莫名其妙丟失。也就是說,在第一計算中,每個對象獲得的值的總和,但在結束時,每個計算出的計算數組的最後對象的總和。

我試圖與,且無需計算的owner部分,參考仍然傳送。該錯誤顯然可以在小提琴中看到,我已經設置了三個按鈕來更改每個值數組。

我還試圖將其設置爲一類:

function Obj(name, values) { 
    ... 
} 

self.newArray.push(new Obj("first", [1, 2, 3]); 

,但同樣的事情發生。

回答

2

排序答案:使用ko.utils.arrayForEach代替人工for循環:

ko.utils.arrayForEach(self.array, function(item) { 
    var obj = { 
     name: ko.observable("new " + item.name()), 
     values: ko.observableArray(item.values()) 
    }; 

    obj.sum = ko.computed({ 
     read: function() { 
      var res = 0; 

      for (var j = 0; j < obj.values().length; j++) 
       res += obj.values()[j]; 

      return res; 
     }, 
     owner: obj 
    }); 

    self.newArray.push(obj); 
}); 

演示JSFiddle

龍答:你的事實,在JavaScript中的變量函數作用域讓你for循環它創建三個局部變量obj但重複使用相同的一個變量,這與閉包相結合咬傷工作,你最終會與您所有的計算引用的最後一個值:

您可以在一個立即執行函數包裹for體解決這個問題:

for(var i = 0; i < self.array.length; i++) { 
    (function(){ 
    var obj = { 
     name: ko.observable("new " + self.array[i].name()), 
     values: ko.observableArray(self.array[i].values()) 
    }; 

    obj.sum = ko.computed({ 
     read: function() { 
      var res = 0; 

      for (var j = 0; j < obj.values().length; j++) 
       res += obj.values()[j]; 

      return res; 
     }, 
     owner: obj 
    }); 

    self.newArray.push(obj); 
    })(); 
} 

演示JSFiddle

+0

感謝一大堆!我仍然習慣於JavaScript範圍。其實,我沒有使用'ko.utils.arrayForEach',但只計算的總和。 – Sljux