In Chrome I first create a continuous tone with the AudioContext:
var audioCtx = new (window.AudioContext || window.webkitAudioContext);
var oscillator = audioCtx.createOscillator();
var gainNode = audioCtx.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);
oscillator.start();
Now I want to stop it after a few milliseconds. So I do this:
setTimeout(oscillator.stop, 500)
This returns the error Uncaught TypeError: Illegal invocation
.
However if I do;
setTimeout(function(){oscillator.stop()}, 500)
it works fine.
I would like to now why the first one doesn't work and returns an error. It seems like the straightforward way to do this.
Your original code doesn't work because the stop
function is passed to setTimeout
without any context - it does not know which object it is supposed to act on. If you invoke it like this:
oscillator.stop();
Then within stop
, the special variable this
is set to the object pointed to by oscillator
. But if you refer to it like this:
var x = oscillator.stop;
The function is not actually invoked. Rather, a reference to the function is simply extracted from oscillator
and stored elsewhere. The function does not remember where it came from, and could be stored in many different variables or object properties at the same time. For example:
var x = {};
x.foo = oscillator.stop;
x.foo();
The last line calls stop
with a context of x
(this
is set to x
) rather than oscillator
. (The function's body will cause errors since stop
makes assumptions about what its context looks like, but the call itself is legal.) Alternatively, if you do this:
var foo = oscillator.stop;
foo();
Then stop
will be called with only a default context. In strict mode, this
will be set to undefined
, and in non-strict mode, this
will be set to window
.
When you do this:
setTimeout(function(){oscillator.stop()}, 500)
The anonymous function invokes stop
with the proper context. If, as suggested by @elclanrs in comments, you do this:
setTimeout(oscillator.stop.bind(oscillator), 500)
It is effectively the same thing: an anonymous function is created that calls stop
with a context of oscillator
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With