vinni
vinni

Reputation: 653

function with variable parameter changes when variable updated

i'm creating functions inside a for-loop with a variable parameter. Unfortunately, as soon as the for-loop runs a second time, it updates the variable and updates all parameters of the previously generated functions. How can I parse a "detached" value in this loop, so it doesn't get overwritten by the next loop?

My current code is this:

var self = this;  

      for (var i = 0; i < wordObjects.length; i++) {
        var wordCurrent = wordObjects[i].word;
        var wordCorrect = wordObjects[i].correct;
        var moreData =  wordObjects[i].moredata;
        var successFunction = wordObjects[i].successFunction;

        //chain all arguments in one array
        variableArray = []
        variableArray = variableArray.concat(wordCorrect);
        variableArray = variableArray.concat(moreData);

        //create function
        var runFunction = function() {self.executeFunctionByName(successFunction, self, variableArray)};
        this.saveFunctions[wordCurrent] = runFunction;
      };

I tried to generate an object with all arrays inside, but then it didn't pass the arrays at all. It looked like this:

var runFunction = function() {self.executeFunctionByName(successFunction, self, variableArray[i])};

I tried to pass variableArray.slice(); but this didn't seem to work either.

Upvotes: 0

Views: 32

Answers (1)

Joshua K
Joshua K

Reputation: 2537

you can solve this by using closures or by using the let statement instead of var. Simply replace var by let.

This works because of the different scoping of let. Take a look at the documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let

Take this example:

for(var i=0;i<5;i++) {
    var j=i;
    setTimeout(function() { console.log(j); }, i*1000);
}

The output is 5x four.

for(var i=0;i<5;i++) {
    let j=i;
    setTimeout(function() { console.log(j); }, i*1000);
}

The output is 0, 1, 2, 3, 4.


To complete the answer: here the solution with a closure. Closures have a factory method and a closure method. The factory method creates a new scope everytime, the closure can use later.

for(var i=0;i<5;i++) {
    setTimeout((function() { var j=i; return function() { console.log(j); }; })(), i*1000);
}

Another way is to store i as the context of the function. This will work also:

for(var i=0;i<5;i++) {
    setTimeout(function() { console.log(this); }.bind(i), i*1000);
}

Upvotes: 1

Related Questions