Knockout JS:observableArray.splice(0)未克隆数组

Knockout JS: observableArray.splice(0) not cloning array?

本文关键字:数组 JS observableArray splice Knockout      更新时间:2023-09-26

背景

我似乎不能失去对我试图克隆的原始阵列的引用。为了具体说明我的问题,假设我有以下内容。

JSBin:http://jsbin.com/fehoq/168/edit

student.scores:  Array[3]
    0: 12
    1: 97
    2: 81

然后,我的dropLowestScores方法打算在scores数组中找到两个最低值,复制并将它们放入属性lowest中。

 student.lowest:  Array[2]
    0: 12
    1: 81

不幸的是,虽然我在lowest中得到了正确的值,而不是从scores中复制它们,但它们是拼接的。不仅如此,我原来数组中的所有值都被耗尽了。

student.scores:  Array[0]

这可能是有道理的,因为我正在调用knockout的splice方法,我在第一次调用splice(0)scores数组的副本上调用它!我不确定这是否重要,但我拼接的可观察阵列由可观察的数字组成。

请参阅下面的脚本了解详细信息,或者参阅上面的JSBin了解完整内容。

请注意,student只是我正在使用的模型。

JS

this.dropLowestScores = function() {
    // find lowest scores for each student
    ko.utils.arrayForEach(_this.students(), function(student){
        //sporting function for observable values in array
        var comparator = function(a,b){
          if(a()<b()){
            return -1;
          } else if(a() > b()){
            return 1;
          } else {
            return 0;
          }
        };                 
        // tmp is a sorted clone of scores
        var tmp = student.scores().sort(comparator).splice(0);
        // set lowest to last two values in tmp array
        student.lowest = tmp.splice((tmp.length-2),tmp.length);
        // see what I'm getting
        console.log(student.fullName());
        console.log('student lowest: ' + student.lowest.length);
        console.log('student scores: ' + student.scores().length);
    });
};

更新

正如edhedges所指出的,slice是正确的方法。comparator的排序也与我的意图相反。

还有一点是,在创建tmp之前,我无法进行排序,否则它会更新视图,而我不希望这样做。

最终版本应该如下所示。

this.dropLowestScores = function() {
    ko.utils.arrayForEach(_this.students(), function(student){
        var comparator = function(a,b){
          if(a()<b()){
            return 1;
          } else if(a() > b()){
            return -1;
          } else {
            return 0;
          }
        };       
        var tmp = student.scores().sort(comparator).slice(0);
        student.lowest = tmp.splice((tmp.length-2),tmp.length-1);
    });
};

您在这里遇到的主要问题是您调用了splice,本应调用slice

正如您所看到的,slice是您试图实现的,但您使用了没有第二个参数的splice,所以您的数组被擦除了。

一旦解决了这个问题,您的comparator函数仍然存在问题。你返回的是最高的两个,而不是最低的两个。

// updated dropLowestScores
this.dropLowestScores = function() {
    ko.utils.arrayForEach(_this.students(), function(student){
        var comparator = function(a,b){
          if(a()<b()){
            return 1;
          } else if(a() > b()){
            return -1;
          } else {
            return 0;
          }
        };                 
        var tmp = student.scores.slice(0).sort(comparator);
        student.lowest = tmp.splice((tmp.length-2),tmp.length);
        console.log(ko.toJSON(student.lowest));
        console.log(ko.toJSON(student.scores));
    });
};