self, within a function. Why is this? Surely
this always refers to the current object?
Short story: nope.
Unlike other languages where it refers to values stored in instance properties, the
this keyword is dynamically bound based on how a particular function is executed. Because of its shifting nature, it can be tricky to keep track of what
this might be referring to when it is called. With a little understanding of the rules behind
this, we can be more confident when writing our code.
There are four rules that help us figure out what
this may be at a particular point in time, and these rules are based on the call-site of the function.
1: Default Binding
When our function is invoked of its own accord, ala:
The call to
this.a resolves to the global variable of the same name. If we were running in strict mode - and you should - we would find that it would be undefined:
2: Implicit Binding
When calling a function as an object method, its call site now has some context and the object in question should be used for the function’s
3: Explicit Binding
We can use the
apply() utilities to force a function to use a particular object for its
this binding. For both utilities, the first parameter is the object to use. As we’ve discovered previously
call() takes a list of parameters, while
apply() is given an array as its second argument.
Both implicit and explicit binding lose their
this binding when passed around. The following pattern helps ensure that this doesn’t happen:
bar() function calls
this bound to our object.
bar() can be passed around, as it is to
setTimeout(), and yet
this remains 2.
It might get a little tiresome wrapping functions for this purpose, so ES5 (supported natively in IE9+, or with ES5-shim) gives us
bind(): a utility that returns a new function that calls the original, with
this set as required.
4: new Binding
new to create a new object, the new object is set as the
So, if the function is called:
thisis the new object;
thisis the specified object;
- as it being a method of an object,
thisis that object;
- in standard execution,
thisis either the
globalobject, or will be
undefinedif using strict mode.
Each function call gets its own
this binding. When a function is executed inside another, we no longer have access to the original
this value. By aliasing it as
self at the top level, we can retain a reference to the original value and make it visible to inner functions.
As for the reasoning behind this convention, Douglas Crockford states that:
…This is a workaround for an error in the ECMAScript Language Specifications which causes
thisto be set incorrectly for inner functions.
bind() in order to explicitly tell a function the context it will be running in.