Search code examples
javascriptadobe-illustratorextendscript

For loop var retains var value from for loop, possible closure?


I'm doing some coding on a program called illustrator which allows you to use JavaScript. This is driving me crazy and I think it's related to closures but I'm not sure if it is or I'm just missing something.

I have the following code:

function runSomeStuff() {
  // some stuff gets done here unrelated variables set
  // after I have the following for loop which opens the document

  for (var currentTemplate = 1; currentTemplate <= 3; currentTemplate++){

    // opens file and does a few if statements... works fine.
    // here I have another for loop where the problem comes up
    for (var i = 1; i <= 18; i++) {
      // run some code here
    }
  }

}

The way it should work is that it should loop 3 times over the first for function which contains the other for function. So it should work like this.

First for function runs

Second for inside of the first runs 17 times then exits, does what it needs to then begins to run again.

The problem is after the first for function runs once, when it loops back again it won't run. The second for function doesn't run again. I added an alert for var i and it gave me 19 when it was trying to run the second time. I would expect var i to be 1 again since it's being re called on the second run. It appears even after it exists it i retains it's value when it was in the for loop so that it's false since i would be greater than 18.

EDIT: Because of the program it's being used in I can't use let or const.


Solution

  • The reason this might happen is due to variable hoisting. I'd recommend checking out if anything changes if you declare your variables at the first line of the function:

    function runSomeStuff() {
      var currentTemplate, i;
    
      // some stuff gets done here unrelated variables set
      // after I have the following for loop which opens the document
    
      for (currentTemplate = 1; currentTemplate <= 3; currentTemplate++){
    
        // opens file and does a few if statements... works fine.
        // here I have another for loop where the problem comes up
        for (i = 1; i <= 18; i++) {
          // run some code here
        }
      }
    }
    

    If the above doesn't work you might want to try managing your own scopes, by moving the for loops into IIFEs:

    function runSomeStuff() {
      // some stuff gets done here unrelated variables set
      // after I have the following for loop which opens the document
    
      (function () {
        for (var currentTemplate = 1; currentTemplate <= 3; currentTemplate++){
    
          // opens file and does a few if statements... works fine.
          // here I have another for loop where the problem comes up
          (function () {
            for (var i = 1; i <= 18; i++) {
              // run some code here
            }
          })();
        }
      })();
    }
    

    This clutters things up quite a bit, but your loops will have their own scope without the use of the let keyword.