Understanding Javascript’s “this” Keyword

3 Comments

Here’s how I explain this to people:

this is a variable. It points to the object which is applied to the function.

There’s nothing innately magical, scary, or confusing about this — it’s a feature, after all. I’m going to attempt to describe it as succinctly as possible, so the information in this post will be rather dense. Take your time reading it.

A brief prologue:
A lot of the misunderstanding arises when developers (like me) who are familiar with Object Oriented programming try to understand Javascript in an Object Oriented fashion.  Javascript uses objects, but is not Object Oriented.

So, if you have preconceived notions of this, now’s the time to let them go.  Take a deep breathe, clear your mind, and let’s get to the bottom of this.

Part One

this is a variable.

Whenever a function is called, a variable called this is instantiated, and its value is set to some object. this is just a variable. It follows the same rules of scoping, you can compare it, you can copy it — it’s a bona fide variable.

It’s incredibly useful to imagine this line of code at the top of each function:
var this = <an object as defined by part two>;

this is only special for three reasons:

• It’s always an object.
• It’s read-only — you cannot set what it refers to
You cannot have a statement which begins with:

this = …
//ReferenceError: invalid assignment left-hand side

though you can modify its properties however you want:

this.foo = …
//works fine — this is an object, after all.
• It’s instantiated and assigned automatically
Much like the arguments object.

Now, let’s find out which object this gets assigned to.

Part Two

this points to the object which is applied to the function.

By default, this refers to the window object.

There are only two ways that this will refer to any other object besides window:

1) If you call a function as a property of an object, then this refers to that object.
2) Calling the “apply” or “call” method of a function – the object is passed as a parameter.

Code speaks for itself:

1
2
3
4
5
// Here's a function. ///
var log_this = function(one, two){
console.log(this, one, two);
}
/////////////////////////

We’re creating a variable called “log_this” which is a function object.

1
2
3
4
5
6
log_this("foo", "bar");
// By default, 'this' refers to window.
// Will log:  window, "foo", "bar"
setTimeout(log_this, 1000);
// Again, by default, 'this' refers to window
// After 1 second, will log: window, undefined, undefined

Window is “this” by default. We were actually calling: window.log_this();

1
2
3
4
5
6
var obj = {};
obj.fn = log_this;
obj.fn("foo", "bar");
// Calling log_this as property of 'obj' object.
// Therefore, this will be obj, and obj will be logged.
// Will log: obj, "foo", "bar"

This is Case 1: We’re calling the function as a property of an object.

1
2
3
4
5
6
7
8
9
var MyObj = function(){}
MyObj.prototype = {fn: log_this};
// Define a function and its prototype.
var o = new MyObj();
// Create an object from the MyObj constructor.
MyObj.fn("foo", "bar");
// Calling a function as property of 'o' object
// Although it's via the prototype, this will still be o
// Will log:  o, "foo", "bar"

Just another way to do the same thing.

1
2
3
4
5
6
7
8
9
var obj = {};
log_this.apply(obj, ["foo", "bar"]);
// Applying obj to log_this function
// Therefore, this will be obj, and obj will be logged.
// Will log: obj, "foo", "bar"
log_this.call(obj, "foo", "bar");
// 'call' is exactly like 'apply'
// instead of an array, it uses extra arguments
// Will log: obj, "foo", "bar"

The magic of “apply” and “call” let us set what this refers to.

1
2
3
4
// You can think of apply/call as doing this:
obj.temp = log_this;
obj.temp("foo", "bar");
delete obj.temp;

This is basically what “apply” and “call” do.

Conclusion

That’s all there is to it. I don’t expect you to grok this right away — take time to let it sink in and reread it a few times.

If you still don’t understand this, then you might consider brushing up on how objects, functions, and variable scoping works in Javascript. These are all simple topics with simple rules, but with big implications. That’s how Javascript works.

If you have any questions, feel free to leave them in the comments.

About Sam

Sam is on the AppNexus UI team, with a focus on building out a modular, scalable, and developer-friendly framework. In addition to Javascript, he's fluent in PHP, MySQL, and will start with Python any day now. He also curates an assortment of items at his desk which includes several kinds of silly putty, a very tall tower of cans, and some gallium.

This entry was posted in Javascript. Bookmark the permalink.

3 Comments
  • Steph

    Reading a lot of different explanations definitely helps understand the ‘this’ keyword and it’s quirks. I did notice that in like 6 of the code block after “This is Case 1: We’re calling the function as a property of an object,” you called the function on ‘MyObj’ instead of ‘o’. Wouldn’t that leave ‘window’ as the value of ‘this’?

    • natlee75

      Actually we’d get a type error since the `fn` method is defined on `MyObj.prototype` and not `MyObj` itself.

  • natlee75

    I’ve found that the easiest way to explain why `Window` is `this` is because the “vanilla” function invocation syntax — `myFunction()` — is really just syntactical sugar for what the JavaScript engine is actually doing: `myFunction.call(Window)`. That `log_this()` is effectively `Window.log_this()` wouldn’t explain invocations of functions declared within other functions.