What is `this` ?

a quick exploration of method and function invocations in Javascript, and the context therein

Okay. I’m going to attempt to make trivial, a somewhat non-trivial subject. I’ve been exploring the inner details of what makes JavaScript, well, JavaScript. One subject that can be quite confusing for many (me too!) is how the this keyword in Javascript works. I’d like to share with you what I’ve found.

We’ll need to understand the difference between a function and a method in Javascript

Method
- a method is simply a function that has an explicit receiver

Function
- does not have an explicit receiver (the global object is the implicit receiver)

So we think, ok, that’s easy. The method is defined as a property on an object. The function is declared in the global space. Done.

Well not really….

See, a method or a function can be the same exact piece of code in memory, how it is invoked is what makes the difference whether it is a method or function, not how it is defined.

line 11— points the global variable ‘globalIntroduce’ to the same function property ‘introduce’ of the person object
line 13 — prints ‘Hello, my name is undefined’; let’s talk about why

Now, is a good time to introduce `this`!

Notice on line-4 of the above snippet where we make a reference to this.name . The keyword this in JavaScript is a reference to the current execution context.

Here is the rule….

  • if it’s a function invocation (no explicit receiver) then the current execution context, referenced in code by the this keyword, is the global object( window in the browser or global in non-browser environments).
  • if it’s a method invocation (has explicit receiver) then the current execution context, referenced in code by the this keyword, is the object in which it is defined (the calling object).
If we refer back to the previous snippet, we see that the call to globalIntroduce() on line-14 prints undefined because of line-4 inside the body of the function. It makes a reference to this.name , as we see clearly, globalIntroduce() is a function invocation meaning it’s this value is a reference to the global window object. So the this reference is saying
lookup the property ‘name’ on the current execution context ( window ), concatenate it to the string ‘Hello, my name is ‘ and print it out”.
When it fails to find a property called name on the global object, it returns undefined as expected.

Let’s look at that same code with one minor change.

Whoa! What happend here?? Notice on line 8 we defined a variable name . In JavaScript, undeclared variables and variables declared in the global scope are defined as properties, you guessed it, on the global object

‘name’ is defined as global variable then we lookup the property ‘name’ on the global object

So we see that variables defined in the global space are actually properties on the global object. There are some nuances to be explored here, including the difference between declared and undeclared variables and how they show up differently in regard to the global object, but those topics are outside of the realm of this blog, if you don’t already understand it, I highly recommend doing some digging on this subject.


Ok, so we understand method invocation vs function invocation, as well as the fact that the this keyword refers to current execution context. Let’s look at some ways provided by JavaScript to control the execution context in our code.

We already pointed out that function invocation will always have the global object as it’s context, and method invocations will have the context of the calling object, but we can change that with some sweet little methods provided by the built-in JavaScript Function prototype object, so they’re available on all functions.

apply(), call(), bind()…..

Function.prototype.apply(context, [array, of, arguments])

and

Function.prototype.call(context, comma, separated, args)

call() and bind() are very similar, in-fact, their only difference is the way they accept extra arguments that are passed along to the receiver function. They invoke any function they are chained to while accepting an explicit context to be set as the this value during execution of the calling function, any extra arguments passed in (as an array in the case of apply(), and as comma separated args in the case of call()), are passed along to the calling function.

However,

Function.prototype.bind(context, extra, args)

bind() is slightly different than the first two, instead of invoking the calling function, it returns a new function that’s a copy of the caller, except with the passed in context permanently bound to the resulting function, and any args passed in will be prepended to the arguments passed in upon invocation of the resulting function.

Let’s look at all this in some code…


The bind() , call() , and apply(), methods are very useful when building objects in actual programs. There are many cases when building objects where nested functions lose the context of the outer containing object and these methods are a life-saver when trying to make your code function as expected. I’ll explore these cases in a later topic on dealing with context loss.

For now, let’s just be glad we have a good grasp on what this is!