Acessar variável externa em loop do encerramento do Javascript

Vejo:

for (var i in this.items) { var item = this.items[i]; $("#showcasenav").append("
  • "); $("#showcasebutton_"+item.id).click(function() { alert(item.id); self.switchto(item.id); }); }

    O problema é que o item.id alertado é sempre o id do último item da matriz (this.items). Como resolver?

    O problema que você tem aqui é que o item da variável muda com cada loop. Quando você está referenciando um item em algum momento posterior, o último valor que ele reteve é ​​usado. Você pode usar uma técnica chamada fechamento (essencialmente uma function que retorna uma function) para rapidamente definir o escopo da variável de maneira diferente.

      for (var i in this.items) { var item = this.items[i]; $("#showcasenav").append("
  • "); $("#showcasebutton_"+item.id).click( // create an anonymous function that will scope "item" (function(item) { // that returns our function return function() { alert(item.id); self.switchto(item.id); }; })(item) // immediately call it with "item" ); }

    Uma nota lateral – vejo que você tem jQuery aqui. Ele tem uma function auxiliar $.each() que pode ser usada com matrizes e pode ser um atalho para simples para / cada loop. Por causa da forma como o escopo funciona nesta chamada – você não precisará usar um encerramento porque “item” já é o parâmetro da function quando foi chamado, não armazenado em um var no escopo da function pai, como era verdade em seu exemplo.

     $.each(this.items,function(i, item) { $("#showcasenav").append("
  • "); $("#showcasebutton_"+item.id).click(function() { alert(item.id); self.switchto(item.id); }); });

    A outra maneira de abordar isso é certificar-se de que os = items[i] negócios são efetivamente feitos chamando uma function. Em resumo, isso:

     for (var i in this.items) { (function(item) { $("#showcasenav").append("
  • "); $("#showcasebutton_"+item.id).click(function() { alert(item.id); self.switchto(item.id); }); })(this.items[i]); }

    A function anônima é um pouco confusa, o que torna preferível ter um não tão anônimo por aí, mas funciona.

    Os closures de Javascript armazenam referências a suas variables, portanto, todos os manipuladores onclick estão usando a mesma variável.

    Você precisa capturar a variável em uma function intermediária, assim:

     function buildClickHandler(pageNumber) { return function() { //Create and return a new function alert(item.id); self.switchto(item.id); } } 

    Em seguida, use essa function para criar manipuladores de click , assim:

     for (var i in this.items) { var item = this.items[i]; $("#showcasenav").append("
  • "); $("#showcasebutton_"+item.id).click(buildClickHandler(item)); }

    Cada chamada para buildClickHandler cria um fechamento separado que possui sua própria variável.

    tente este loop

     for (var i=0; i < this.items.length; i++) { this.items[i] }; 

    Eu sei muito bem que este é um post antigo, mas parece que as pessoas geniosas que projetam o jQuery (que eu imaginei que você deve estar usando) fizeram a solução mais ideal para o seu problema, como eu o entendo.

    Na nova versão 1.4 da biblioteca, eles adicionaram a function jQuery.proxy () . Isso permite que você modifique eficientemente o contexto / escopo da function que você está chamando – feito da maneira jQuery, que garante que você pode parar de usar técnicas que potencialmente poderiam atrapalhar as coisas.