2009-08-21 1 views
4

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

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

Как заставить его не указывать на счётчик цикла, но создать новый PageNumber на одну итерацию, которая содержит текущее значение счётчик цикла?

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) 
); 
+0

Что такое result.StartingPoint? –

+0

Eh a объект, возвращенный из асинхронного вызова метода. –

ответ

9

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

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

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

+0

Так что в принципе мне нужен метод для создания метода события, чтобы ясность ясности. –

+0

Да. Поскольку область JS ограничена функциями, а не блоками, вам необходимо создать новую функцию. Это, по сути, то, что различные JS libs заставляют вас делать со своими методами подключения событий. – seth

0

Замыкание OnClick не будет поддерживать его объем, поэтому он не будет иметь возможность доступа к результату.

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

+0

И в этот момент вы можете просто использовать dojo.forEach и dojo.connect – seth

1

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

var pageNumber = new Number(loopCounter); // force coercion 
+0

Не будет ли это сделать только ссылку на номер страницы, и этот метод все еще указывает на loopCounter? –

5

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

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

+0

Интересные, старые добрые динамические области. – Zoidberg

2

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)); 
+0

Жаль, что я мог бы отметить два правильных. Скорее всего, я бы использовал jquery, как вы предполагали, но я хотел, чтобы это было общим, так что больше людей ответят. –

Смежные вопросы