2014-01-11 232 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