我有以下函数为Highcharts图表构建一个或多个y轴,尽管我的问题与Highcharts API很少或没有任何关系。
_constructYAxes: function(yAxes) {
if (yAxes) {
var highChartYAxes = [];
for (var i = 0; i < yAxes.length; i++) {
var kpiUnits = yAxes[i].units;
var axisUnits = 'units ' + i;
var axisLabel = 'label ' + i;
// construct an Highcharts y-axis object
var yAxis = {
labels: {
formatter: function() {
return this.value + ' ' + axisUnits;
}
},
title: {
text: axisLabel
},
};
highChartYAxes.push(yAxis);
}
// pass all the y-axes to the chart
this.chartOpts.yAxis = highChartYAxes;
}
}
问题在于,即使正确显示label
,每个y轴也使用相同的title
。两者之间的区别在于前者是通过调用函数来计算的
labels: {
formatter: function() {
return this.value + ' ' + axisUnits;
}
},
因此,如果我有一个包含3个y轴的图表,则所有标签上都会出现“单位2”标签。
我认为问题是formatter
函数在循环的最后一次迭代中关闭axisUnits
的值,这样当调用函数时(通过Highcharts),它使用相同的函数每次axisUnits
的值。
我可以做什么来强制函数在每次调用时使用axisUnits的第i个值?
显然,我对JavaScript范围的理解有些缺乏(我常常对this
在不同情况下的评估感到惊讶)。如果有人知道一些可以帮助我顺利完成的好的在线资源,请按照我的方式发送给他们。
答案 0 :(得分:2)
使用匿名函数包装器:
formatter: function(units) { //"Private" variable axisUnits
return function() {
return this.value + ' ' + units;
};
}(axisUnits)
由于匿名函数包装器,每个formatter
函数现在将在创建时引用axisUnits
变量。
答案 1 :(得分:2)
axisLabel
直接作为字符串传递,不会更改。
但是,axisUnits
不直接传递。它仅在调用函数时获取。问题是for
循环不会创建新范围,因此对于所有迭代,只有一个axisUnits
,这会导致所有标签具有相同的文本。
您可以通过创建闭包来解决此问题。这样,字符串 直接传递并“冻结”:
formatter: (function(x) { // x won't change
return function() {
return this.value + ' ' + x;
};
})(axisUnits);
答案 2 :(得分:0)
我认为关于闭包和循环问题你是对的
请在这里阅读http://www.mennovanslooten.nl/blog/post/62 - 它有帮助吗?
答案 3 :(得分:0)
使用function.bind(this, args)
:https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
如果浏览器没有它,它是新的,很棒且易于提供。所以在这种情况下你会写:
formatter: (function(axisUnits) {
return this.value + ' ' + axisUnits;
}).bind(this, axisUnits);
正如你所看到的那样,写一些东西比匿名包装函数更容易理解。