Возможный доступ к измененной проблеме закрытия ... Как победить? - PullRequest
4 голосов
/ 21 августа 2009

По какой-то причине, независимо от того, что pageNumber заканчивается последним значением в цикле для loopCounter. Теперь я бы понял, что если бы я непосредственно использовал loopCounter в самом замыкании, но это не так. Как вы можете видеть из кода ниже, я создаю новую переменную внутри замыкания, чтобы принять текущее значение loopCounter.

Единственное, что я могу понять, это (при условии, что javascript обрабатывает все как ссылочный тип), что pageNumber принимает ссылку на loopCounter, поэтому независимо от того, сколько раз я создаю новый pageNumber, он всегда указывает на объект loopCounter. Следовательно, любое значение loopCounter, которое заканчивается в конце, будет значением, на которое будет указывать любой pageNumber.

Как мне сделать так, чтобы он не указывал на loopCounter, а создавал новый pageNumber для каждой итерации, содержащий текущее значение loopCounter?

for (var loopCounter = result.StartingPoint; loopCounter <= result.HighestPageCount; loopCounter++)
{
  ...
  var newDiv = document.createElement('div');
  ...
  //trying to remove the reference to loopCounter
  var pageNumber = loopCounter;
  newDiv.onclick = 
    function(event) 
    { //Right here ---V
      getResultUsingUrl(result.PagerPreLink + "&pageNumber=" + pageNumber);
    };

  ...
}

РЕШЕНИЕ

Благодаря паре ответов ниже:

function createClickMethod(loopCounter, link)
{
    var pageNumber = loopCounter;

    return function(event) { getResultUsingUrl(link + "&pageNumber=" + pageNumber); };
}

и я могу позвонить как:

newDiv.onclick = createClickMethod(loopCounter, result.PagerPreLink);

Или, если я хочу использовать jQuery ... предлагается ниже:

jQuery(newDiv).click
(
    createClickMethod(loopCounter, result.PagerPreLink)
);

Ответы [ 5 ]

9 голосов
/ 21 августа 2009

Как и все остальные говорили, это проблема с областью видимости. Без использования библиотеки JS вы можете сделать что-то вроде этого:

newDiv.onclick = (function() {
    var num = loopCounter;
    return function(evt) {
        console.log( num );
    }
})();

Вам просто нужно создать еще одно замыкание вокруг значения.

5 голосов
/ 21 августа 2009

Вы не создаете новый pageNumber каждый раз. У вас есть только один. Область действия в JavaScript не выходит за пределы области действия. Любой "var", который вы объявляете в функции - внутри или вне цикла - работает точно так же, как если бы вы объявили его в самом начале функции.

http://javascript.crockford.com/code.html

2 голосов
/ 21 августа 2009

В Javascript-закрытиях хранятся ссылки на их переменные, поэтому все ваши обработчики onclick используют одну и ту же переменную.

Вам нужно захватить переменную в промежуточной функции, например:

function buildClickHandler(pageNumber) {
    return function(event)  {    //Create and return a new function
        getResultUsingUrl(result.PagerPreLink + "&pageNumber=" + pageNumber);
    }
}

Затем используйте эту функцию для создания обработчиков onclick, например:

for (var loopCounter = result.StartingPoint; loopCounter <= result.HighestPageCount; loopCounter++) { 
    //...

    var newDiv = document.createElement('div');

    newDiv.onclick = buildClickHandler(loopCounter);
}

Каждый вызов buildClickHandler создает отдельное замыкание, которое имеет свою собственную переменную.


В качестве альтернативы рассмотрите возможность использования jQuery для выполнения DOM-манипуляций; это намного проще, чем сырые DOM API.

В вашем примере вы могли бы написать

$('<div />').click(buildClickHandler(loopCounter));
1 голос
/ 21 августа 2009

Является ли result.StartingPoint действительно примитивным типом, например, фактический тип номера? Если нет, то, возможно, происходит то, что вы получаете ссылку на этот объект, а затем конкатенация строк выполняет приведение типов для вас. Попробуйте вместо этого:

var pageNumber = new Number(loopCounter); // force coercion
0 голосов
/ 21 августа 2009

Закрытие onclick не будет поддерживать свою область действия, поэтому оно не сможет получить доступ к результату.

Взгляните на dojo.hitch , чтобы найти простое и мощное решение, позволяющее контролировать его область действия.

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