JavaScript Scoping - PullRequest
       1

JavaScript Scoping

1 голос
/ 14 октября 2011

У меня есть следующая функция, которая создает одну или несколько осей Y для диаграммы Highcharts, хотя моя проблема не имеет ничего общего с API Highcharts.

_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 каждый раз.

Что можно сделать, чтобы заставить функцию использовать i-ое значение axisUnits каждый раз, когда она вызывается вместо этого?

Очевидно, что мое понимание области видимости JavaScript несколько отсутствует (меня часто удивляет то, что this оценивает в разных контекстах).Если кто-нибудь знает о некоторых хороших интернет-ресурсах, которые могут помочь мне разобраться в этом, отправьте их мне.

Ответы [ 4 ]

2 голосов
/ 14 октября 2011

Использовать оболочку анонимной функции:

formatter: function(units) { //"Private" variable axisUnits
    return function() {
        return this.value + ' ' + units;
    };
}(axisUnits)

Благодаря оболочке анонимной функции каждая функция formatter теперь будет ссылаться на переменную axisUnits во время создания.

2 голосов
/ 14 октября 2011

axisLabel передается в виде строки напрямую и не изменяется.

Однако axisUnits - это , а не - передается напрямую.Он выбирается только при вызове функции.Проблема в том, что цикл for не создает новую область, поэтому для всех итераций существует только одна axisUnits, в результате чего все метки имеют одинаковый текст.

Это можно решить, создавзакрытиеТаким образом, строка напрямую передается и «замораживается»:

formatter: (function(x) { // x won't change
               return function() {
                   return this.value + ' ' + x;
               };
           })(axisUnits);
0 голосов
/ 10 февраля 2012

Использование 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);

Как видите, написать немного меньше, чем анонимную функцию переноса и легче понять.

0 голосов
/ 14 октября 2011

Я думаю, что вы правы насчет замыкания и проблемы петли

Пожалуйста, прочитайте здесь http://www.mennovanslooten.nl/blog/post/62 - это помогает?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...