Aptary Aptary -4 years ago 207
Javascript Question

Variable defined within function causing reference error: not defined

I'm working my way through some web audio tutorials in this O'Reilly Book: http://chimera.labs.oreilly.com/books/1234000001552/ch02.html#s02_2

The following code is supposed to create a system to pause an audio file and resume play.

// Assume context is a web audio context, buffer is a pre-loaded audio buffer.
var startOffset = 0;
var startTime = 0;

function pause() {
// Measure how much time passed since the last pause.
startOffset += context.currentTime - startTime;

function play() {
startTime = context.currentTime;
var source = context.createBufferSource();
// Connect graph
source.buffer = this.buffer;
source.loop = true;
// Start playback, but make sure we stay in bound of the buffer.
source.start(0, startOffset % buffer.duration);

However, running the
function results in the following error:

Uncaught ReferenceError: source is not defined

Now from my point of view, this is caused because
has been defined with the
keyword making it scoped to the
function and therefore inaccessible to
. Removing the
keyword does indeed solve the problem. Can someone just reassure me that my reasoning is correct? Is this just a typo, or is there some underlying principle that I'm not understanding? (I've checked the errata for the book and there's no mention of it there.)

Answer Source

Declaring a variable in a function makes it a local variable, i.e. it only exists in that function and thus can only be referenced in that function. Declaring it as a global variable will make it available to any Javascript function, but you generally want to pollute the global namespace as little as possible:

function AudioPlayer(buffer) {
  this.startOffset = 0;
  this.startTime = 0;      
  this.source = null;
  this.buffer = buffer;

AudioPlayer.prototype.pause = function() {
  if (!this.source) {
  // Measure how much time passed since the last pause.
  this.startOffset += context.currentTime - this.startTime;

AudioPlayer.prototype.play = function() {
  this.startTime = context.currentTime;
  this.source = context.createBufferSource();
  // Connect graph
  this.source.buffer = this.buffer;
  this.source.loop = true;
  // Start playback, but make sure we stay in bound of the buffer.
  this.source.start(0, this.startOffset % this.buffer.duration);

Which allows you to call these functions like so:

var player = new AudioPlayer(buffer);
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download