1

I have an issue with variable scope in a callback. It's a little hard to explain, so here's the simplified code I'm using. Note that I'm using ES6.

class Foo {
    constructor() { /* ... */ }

    // Execute 'callback' after 'delay' has passed (works fine)
    timer(delay, callback) { /* ... */ }

    // Emit a sound of 'frequency' for 'duration' (works fine)
    sound(duration, frequency) { /* ... */ }

    // Play each 'frequency' for 'duration'
    music(duration, frequencyArray) {
        var that = this;
        for (var i = 0; i < frequencyArray.length; i++) {
            var freq = frequencyArray[i];
            this.timer(duration*i, function() {
                // The line below doesn't work properly
                // 'freq' is always equal to the last value of the array
                that.sound(duration, freq); 
            });
        }
    }
}

// Usage
var F = new Foo();
F.music(200, [150, 200, 250]);

In the example above, instead of hearing 3 different notes (150, 200, 250), I hear 3 times the same note of frequency 250.

I understand why (the var freq is equal to 250 when the callback is actually called, but I don't know how to fix that. Any idea?

Thanks!

Thomas
  • 887
  • 1
  • 10
  • 15

1 Answers1

0

When you are using a delayed callback in a loop, you have to create a special scope for this call. To do that, you have 2 main solutions : create a fonction in you class or a local anonymous function like (function(localVar) { /* Run your delayed callback here using local variables passed to this anonymous function */ })(localVar);

This could be easily explained by the fact you callback is using the scope of the loop, si for each loop, you variable's value changes and when the callback is called, your variable has the last value.

Loenix
  • 1,057
  • 1
  • 10
  • 23