【问题标题】:d3 - problems with tickFormat + mutable variable accessible from closure?d3 - 可从闭包访问的 tickFormat + 可变变量的问题?
【发布时间】:2016-08-02 17:53:07
【问题描述】:

我有一个对象数组,将实际刻度值映射到我想要刻度的显示标签。换句话说,该对象以刻度值为键并给出显示值。

var tickMap = [{"27": 27, "28": 28, "29": 29, "30": 30, "31": "Test", "32": "Test2", "33": 33}, 
               {"50": 50, "58": "Test3", "66": 66, "74": 74, "82": 82, "90": 90}];

然后我循环这个,并使用tickFormat 属性,尝试返回每个刻度值的显示值。 d 是来自tickValue 的刻度的实际数值:

for (var i = 0; i < tickMap.length; i++) {
  index = i;
  dimensions[i] = {
    'tickFormat': function(d) {
      return tickMap[index][d];
    },
    // other dimension properties are here, including arrays of 
    // the actual tick values in the tickValues property.
  }
};

但这似乎只适用于数组中的第二个(或最后一个)轴。我没有使用tickMap[i][d],而是尝试全局声明index,然后将i 的值分配给index,但这并没有帮助。

我还收到错误“可变变量可从闭包中访问”。

我不确定如何解决这个问题。任何帮助将不胜感激。

【问题讨论】:

    标签: javascript d3.js


    【解决方案1】:

    您的问题是 JS 中的函数维护对在其闭包中创建的实际变量的引用,而不是值。这意味着您的代码中的i对于每个tickFormat 函数 都将是相同的i(相同的内存位置),其中包含循环完成时它获得的tickMap.length 的值。

    ES6 解决方案

    如果您可以使用 ES6,只需使用 let 而不是 var,一切都会正常工作,因为 let 会为每次循环迭代创建一个新变量,这意味着每个 tickFormat 函数将获得自己的 @987654330 副本@:

    for (let i = 0; i < tickMap.length; i++) {
      dimensions[i] = {
        'tickFormat': function(d) {
          return tickMap[i][d];
        }
      }
    };
    

    ES5 及以下解决方案

    否则,您必须手动执行相同的操作,方法是将循环代码包装在 Immediately Invoked Function Expression (IIFE) 中并将 i 传递给它。这将在 IIFE 的参数中创建一个新变量,该变量将在每次迭代时保存在创建 IIFE 时传递给 IIFE 的 i 的值:

    for (var i = 0; i < tickMap.length; i++) {
      dimensions[i] = (function iife(index) {
        return {
        'tickFormat': function(d) {
          return tickMap[index][d];
        };
      })(i); // <-- here you pass `i` as the `index`, maintaining a unique reference and thus the correct value for each `i`
    };
    

    【讨论】:

    • 你就是男人!非常感谢,这个解释帮助很大。
    猜你喜欢
    • 2014-10-27
    • 2015-09-18
    • 2012-11-28
    • 2013-05-19
    • 1970-01-01
    • 1970-01-01
    • 2013-12-30
    • 1970-01-01
    • 2017-06-18
    相关资源
    最近更新 更多