JavaScript范围

时间:2011-10-14 10:03:41

标签: javascript scope

我有以下函数为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在不同情况下的评估感到惊讶)。如果有人知道一些可以帮助我顺利完成的好的在线资源,请按照我的方式发送给他们。

4 个答案:

答案 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);

正如你所看到的那样,写一些东西比匿名包装函数更容易理解。