繁体   English   中英

JavaScript范围

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM