Wes Contreras
Wes Contreras

Reputation: 23

How do I determine the Execution Context for a JavaScript callback function?

When a function is called as an object property, this is set to the parent object. There are similar rules that apply to calling a function as a Constructor, or an event handler, but after browsing more articles on JS Scope than I can count, and digging into the ECMA5.1 specification, I've been unable to sort out exactly how Execution Context is set when a function is passed as a callback.

This code makes it clear that a method passed as a callback to another method, even within the same object, reverts to the global Execution Context (both in a browser and in Node.js).

var name = 'global';
var self = function() {
    return this.name;
}
var cback = function(ff) {
    return ff();
}
var parent = {
    name: 'parent',
    cback: function(ff) {
        return ff();
    },
    self: function() {
        return this.name;
    }
}
console.log(parent.cback(parent.self));  // Returns "global"

Can anyone help me understand why the callback is executed in a global context instead of within the parent object's context? My best guess is that any function passed as an argument has its previous execution context replaced when it's assigned to a local variable (ff in the example above), which means invoking it passes an undefined thisArg and devolves to global context (barring strict mode, or being attached as a method to a new object before execution), but I'm hesitant to rely on that without it being a bit more than a guess.

Upvotes: 2

Views: 1250

Answers (2)

Bergi
Bergi

Reputation: 664256

how Execution Context is set when a function is passed as a callback

I think the key to understanding is that those processes are completely independent.

any function passed as an argument has its previous execution context replaced when it's assigned to a local variable

Not really. A function by itself does not have any execution context at all.

The execution context only gets created when calling the function. And only how the function is called determines the properties of the execution context, such as its this value.

For example,

When a function is called as an object property, this is set to the parent object.

such as parent.cback(…). The called function being referenced by a property, the base reference (parent) will become the this context of the call.

Alternatively, when a function is called as a plain function, this is set to undefined (or the global object in sloppy mode) - such as ff().

For the other alternatives, have a look at the MDN refernce on the this keyword.

Upvotes: 2

hugomg
hugomg

Reputation: 69934

The rules for this in callbacks are the same as the rules for non-method functions. The thing that really matters is if the function call looks like f() (non-method), x.f() (method call) or new f() (constructor)

Can anyone help me understand why the callback is executed in a global context instead of within the parent object's context?

Sadly, this is one of those big Javascript warts that we have to live with. That said, if you are running in strict mode the this is null instead of the global object, which is more sane. Additionally, in ES6 there will be "fat arrow" => lambdas, which inherit the this from their lexical context (this means it gets its this from the outer function, just like regular variables)

Upvotes: 1

Related Questions