[英]JavaScript scoping
我有以下函数为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;
}
}
问题是即使title
显示正确,每个y轴也使用相同的label
。 这两者之间的区别在于前者是通过调用函数来计算的
labels: {
formatter: function() {
return this.value + ' ' + axisUnits;
}
},
因此,如果我有一个包含3个y轴的图表,则所有标签上都会出现“单位2”标签。
我认为问题是formatter
函数在循环的最后一次迭代中关闭了axisUnits
的值,这样当调用函数时(通过Highcharts),它每次都使用相同的axisUnits
值。
我可以做什么来强制函数在每次调用时使用axisUnits的第i个值?
显然,我的JavaScript作用域的理解是有所欠缺(我经常由什么惊讶this
评估在不同的上下文来)。 如果有人知道一些可以帮助我顺利完成的好的在线资源,请按照我的方式发送给他们。
使用匿名函数包装器:
formatter: function(units) { //"Private" variable axisUnits
return function() {
return this.value + ' ' + units;
};
}(axisUnits)
由于匿名函数包装器,每个formatter
函数现在将在创建时引用axisUnits
变量。
axisLabel
直接作为字符串传递,不会更改。
但是, 不直接传递axisUnits
。 它仅在调用函数时获取。 问题是for
循环不会创建新范围,因此对于所有迭代,只有一个axisUnits
,这会导致所有标签具有相同的文本。
您可以通过创建闭包来解决此问题。 通过这种方式,将字符串直接传递及“冻结”:
formatter: (function(x) { // x won't change
return function() {
return this.value + ' ' + x;
};
})(axisUnits);
我认为你关闭和循环问题是正确的
请在这里阅读http://www.mennovanslooten.nl/blog/post/62 - 有帮助吗?
使用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);
正如您所看到的那样,写入比匿名包装功能更容易理解。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.