简体   繁体   中英

Javascript: Issue with variable scoping and anonymous function

I have this sample code:

function(){
  var events = [];
  var pages = ["a", "b", "c"];
  for(var pageIndex in pages){
    var pageName = pages[pageIndex];
    var e = function(){
      console.info(pageName);
    };
    events.push(e);
  }
  for(var eventIndex in events){
   console.info("index: " + eventIndex);
   events[eventIndex]();
  }
}

Output:

index: 0 
c 
index: 1 
c 
index: 2 
c 

Desired output:

index: 0 
a 
index: 1 
b 
index: 2 
c 

Is there a standard practice for this?

Welcome to closures in javascript, you need to wrap the function in an IIFE or immediately invoked function expression which creates a closure and saves the state in its scope:

(function(){

  var events = [];
  var pages = ["a", "b", "c"];

  for(var pageIndex in pages){
    var pageName = pages[pageIndex];
    var e = (function(pageName){
      return function() {console.info(pageName);};
    }(pageName));
    events.push(e);
  }

  for(var eventIndex in events){
   console.info("index: " + eventIndex);
   events[eventIndex]();
  }
}());

Copy and paste it into the console debugger to test...

Each e function that you create is a closure that accesses the external variable pageName from the enclosing code. The pageName that it will see is the value at the time the function is run . So at the end of your loop pageName is "c" , so that is what all of the functions will use when they are executed.

You can fix this by wrapping your function in the following way, which will essentially bind the current value of pageName to the function you create:

function(){
  var events = [];
  var pages = ["a", "b", "c"];
  for(var pageIndex in pages){
    var pageName = pages[pageIndex];
    var e = (function(data) {
      return function() {
        console.info(data);
      };
    })(pageName);
    events.push(e);
  }
  for(var eventIndex in events){
   console.info("index: " + eventIndex);
   events[eventIndex]();
  }
}

I found the answer here . I need to wrap my function in another function. How nifty.

    Template.index.test = function(){
         var events = [];
         var pages = ["a", "b", "c"];
         for(var pageIndex in pages){
           var pageName = pages[pageIndex];
           var e = function(pageName) {
             return function(){
               console.info(pageName);
             };
           }(pageName);
           events.push(e);
         }
         for(var eventIndex in events){
           console.info("index: " + eventIndex);
           events[eventIndex]();
         }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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