You are viewing a read-only archive of the Blogs.Harvard network. Learn more.

Javascript Callback Scope

I ran into an annoying issue with js callback scope recently and wanted to document it for myself somewhere. Callbacks are super simple at the core — passing a function as a parameter to another function.

callbackFn =  function(){
  alert("bam");
}
firstFn = function(callback){
  callback();
}
firstFn(callbackFn);

That’s all well and good so long as everything is in the global scope. But that’s just bad practice.

So in OO js, you’d have something like this:

Obj = {
  callbackFn: function(){
    alert("bam");
  },
  firstFn: function(callback){
    callback();
  },
  secondFn: function(){
    this.firstFn(this.callbackFn);
  }
}
Obj.secondFn();

This will actually be executing callbackFn in the global scope. The ‘this’ just gets lost. Note that you may only notice this if you’re expecting the this of callbackFn to find what’s in your obj (the above sample will probably work just fine).

Obj = {
  myalert: function(){
    alert("bam!");
  },
  callbackFn: function(){
    this.myalert();
  },
  firstFn: function(callback){
    callback();
  },
  secondFn: function(){
    this.firstFn(this.callbackFn);
  }
}
Obj.secondFn();

There, that one will fail.

The solution is to use the apply() function.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply

Obj = {
  myalert: function(){
    alert("bam!");
  },
  callbackFn: function(){
    this.myalert();
  },
  firstFn: function(callback, callbackObj){
    callback.apply(callbackObj);
  },
  secondFn: function(){
    this.firstFn(this.callbackFn, this);
  }
}
Obj.secondFn();

And that will work as intended.