从可观察数组中获取对象

时间:2016-02-13 05:10:40

标签: javascript knockout.js

为什么在此代码中m“未定义”:

currentViewModel = ko.mapping.fromJS(viewModel);
currentViewModel.getReport = function(reportId) {
    for(var i=0;i<currentViewModel.availableReports().length;i++) {
        if(currentViewModel.availableReports()[i].id == reportId) {
            var m = currentViewModel.availableReports()[i];
            return currentViewModel.availableReports()[i];
        }
    }
}

我将getReport()称为onclick事件,我想将报表对象发送到视图(模态)我可以在availableReports上做一个foreach,它就在那里。当我运行调试器时,它遍历数组并找到正确的数组。但是为什么我不能把它拉出阵列呢? “m”仍未定义,函数返回undefined。

我在这里缺少什么?

编辑:此处有一个跟进问题: Can knockout.js wait to bind until an onClick?

2 个答案:

答案 0 :(得分:2)

您只需将if(currentViewModel.availableReports()[i].id ...更改为if(currentViewModel.availableReports()[i].id() ...,因为映射id后会成为可观察的,即函数。

更新的代码:

currentViewModel = ko.mapping.fromJS(viewModel);
currentViewModel.getReport = function(reportId) {
    for (var i = 0; i < currentViewModel.availableReports().length; i++) {
        if (currentViewModel.availableReports()[i].id() == reportId) {
            var m = currentViewModel.availableReports()[i];
            return currentViewModel.availableReports()[i];
        }
    }
}

演示 - Fiddle

答案 1 :(得分:0)

我会在这里重复@NikolayErmakov's answer中的解决方案,但想要添加两件事来获得更完整的答案。你以:

结尾
  

... m仍未定义,函数返回undefined

     

我在这里缺少什么?

你错过了两件事:

  1. var m内第一个语句的if位是hoisted到当前范围的顶部(函数的顶部)。这就是为什么调试器可以告诉你m是什么,即使你从未到达它所在的代码行。
  2. 如果函数调用到达函数的末尾(就像您的情况一样,因为您从未进入if)而没有看到明确的return语句,it will return undefined
  3. 为了更好地理解这一点,你应该像这样解释你的功能:

    currentViewModel.getReport = function(reportId) {
      var m;
    
      for (var i = 0; i < currentViewModel.availableReports().length; i++) {
        if (currentViewModel.availableReports()[i].id == reportId) {
          m = currentViewModel.availableReports()[i];
          return currentViewModel.availableReports()[i];
        }
      }
    
      return undefined;
    }
    

    有些人(e.g. Douglas Crockford)建议将var语句放在函数的顶部,尽管这在某种程度上是一种风格问题。我不认为很多人在函数结束时显式返回undefined,但在你的情况下,我可能明确表示该场景并返回null(或抛出一个甚至出错。

    正如所承诺的那样,我将重复实际解决方案,因为我同意另一个答案:

    • 您需要调用id作为函数来获取其值(因为mapping插件将映射到observable() s。

    另外:

    • 我只检索一次数组
    • 我建议使用===代替==

    这是我的v0.5版本:

    currentViewModel.getReport = function(reportId) {
        var m = null, reports = currentViewModel.availableReports();
    
        for (var i = 0; i < reports.length; i++) {
            if (reports[i].id() === reportId) {
                m = reports[i];
                return m;
            }
        }
    
        return m;
    }
    

    但我会优化它到这个v1.0:

    currentViewModel.getReport = function(reportId) {
        var reports = currentViewModel.availableReports();
    
        for (var i = 0; i < reports.length; i++) {
            if (reports[i].id() === reportId) {
                return reports[i];
            }
        }
    
        return null;
    }
    

    为了完整起见,这是另一个在数组上使用filter的版本:

    currentViewModel.getReport = function(reportId) {
      var reports = currentViewModel.availableReports().filter(function(r) { return r.id() === reportId; });
      return reports.length >= 1 ? reports[0] : null;
    }