我有一个对象数组,它们将实际的刻度值映射到我希望刻度线的显示标签。换句话说,对象键入刻度值并给出显示值。
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
属性,尝试返回每个tick值的显示值。 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
,但这并没有帮助。
我也得到了错误&#34;可以从闭包中获取可变变量&#34;。
我不确定如何解决这个问题。任何帮助将不胜感激。
答案 0 :(得分:1)
您的问题是JS中的函数维护对其闭包中创建的实际变量的引用,而不是值。这意味着代码中的i
与每个i
函数相同tickFormat
(相同的内存位置),包含tickMap.length
的值它在循环结束时得到了。
ES6解决方案
如果您可以使用ES6,只需使用let
而不是var
,一切都应该有效,因为let
为每个循环迭代创建一个新变量,这意味着每个tickFormat
函数会获得自己的i
:
for (let i = 0; i < tickMap.length; i++) {
dimensions[i] = {
'tickFormat': function(d) {
return tickMap[i][d];
}
}
};
ES5&amp;波纹管解决方案
否则,您必须手动执行相同操作,方法是将循环代码包装在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`
};