Search code examples
javascriptscopereturn

How can I increment the value of a parameter in an object using a function?


I want to be able to increment/change the value of a parameter inside an object. I want the value to change by accessing the value of a variable that is incrementing inside another function.

The example code below shows what I am trying to do. I would like options.number to increase as i inside masterLoop increases.

I know that i isn't defined in the scope of function calc(), but I can't think of a way to retrieve the value of i while maintaining this general code structure.

(function masterLoop(i) {
  setTimeout(function() {
    ++i;
    masterLoopStage = i;
    console.log('Stage is: ' + i);
    masterLoop(i);
  }, 5000)
})(1);

function calc() {
  number = i; // I know i isn't defined in this scope, but I can't figure out how access the incrementing value of i inside this function  
  return number;
}

var options = {
  number: calc() // I want this vale to increase along with i inside masterLoop() 
};

setInterval(function() {
  console.log(options.number);
}, 5000);

Typically, in cases like this, I would try to use a return to retrieve a value, but I wasn't able to find a solution with that either since the incrementing value is inside a setInterval and thus its scope isn't available to the return.

Here is an example of that:

function calc() {
  var foo = 1;
  setInterval(function() {
    var foo = foo + 1;
  }, 1000);
  return foo; // the incrementing value of foo is not available outside the scope of setIterval, so this won't work. The return also won't work inside setInterval.
}

var optionsConstant = {
  maxVolume: 10
};

var options = {
  maxVolume: optionsConstant.maxVolume + calc() // I want calc() to be able to increment along with foo in the setInterval above.
};

setInterval(function() {
  var maxVolume = options.maxVolume;
  console.log('maxVolume:   ' + maxVolume);
}, 5000);


Solution

  • Taking your second attempt, you could make calc an immediately invoked function expression -- providing a closure -- and in it return a function that has access to foo.

    Then, to keep the final syntax of options.maxVolume, you should define that property as a getter, so that in fact it will execute some code when accessed, calling calc():

    var calc = (function () { // create closure for foo
        var foo = 1;
        setInterval(function() {
            foo = foo + 1; // remove var!
        }, 100);
        return function calc() { // return a function
            return foo;
        }
    })();
    
    var optionsConstant = {
        maxVolume: 10
    };
    
    var options = {
        get maxVolume() { // make it a getter
            return optionsConstant.maxVolume + calc();
        }
    };
    
    setInterval(function() {
        var maxVolume = options.maxVolume;
        console.log('maxVolume:   ' + maxVolume);
    }, 500);