Understanding how this
works in JavaScript is fairly simple. Knowing what this
points to however… that is much more difficult. Scope and context become important concepts to understand. Knowing exactly what this
points to and why within each function/method in your JavaScript code can be utterly confusing. Hopefully the rules and corresponding examples below provide clarity on this
.
TL;DR — The four rules presented for determining what this
in JavaScript points to boil down to one simple question: What is the calling object?
Precedence of the four rules:
(The JavaScript interpreter will ask in this order)
- Is the function called by
new
? - Is the function called by
call()
,apply()
, orbind()
? - Is the function called as a method, ie:
obj.func()
? -
Is the function called in the global scope?
- If strict mode is enabled, return
undefined
. - Otherwise, return the global object, ie:
window
.
- If strict mode is enabled, return
In JavaScript functions don’t know where they live. They only know how they are called.
Alexis Abril, Advanced JS Fundamentals to jQuery & Pure DOM Scripting (What is “this”: 9:09–9:13)
-
Whenever a function is contained in the global scope, the value of
this
inside of that function will be thewindow
object.// Basic Function // -------------- function greetMe(name) { console.log('Hello ' + name); console.log(this); } greetMe('John');
Functions within the global scope are in fact methods on the
window
object. So, callinggreetMe('john');
is no different than callingwindow.greetMe('john');
Therefore,this
inside of thegreetMe
function points towindow
. -
Whenever a function is called by a preceding dot, the object before that dot is
this
.// Object Method // ------------- var greetMe = { greeting: 'Hello ', speak: function(name) { console.log(this.greeting + name); console.log(this); } } greetMe.speak('John');
This example is similar to what we saw above with
window.greetMe
. Here, instead ofwindow
we have thegreetMe
object on the left of the dot. Therefore,this
inside of thespeak
method points togreetMe
.// Method Assignment // ----------------- var greeting = 'Salutations ', greet = greetMe.speak; greet('John');
While this example appears to break rule 2, it doesn’t because it actually applies to rule 1. In this example, we establish two global variables:
greeting
andgreet
. Remember, since these variables are declared in the global scope, they are actually just properties on thewindow
object. Therefore, whengreet
is called, while it points to thegreetMe.speak
method, it is executed in the context of thewindow
object. It would be as if you executedwindow.greet('John');
. Therefore,this
inside of thegreet
function points towindow
. -
Whenever a constructor function is used,
this
refers to the specific instance of the object that is created and returned by the constructor function.// Constructor Function // -------------------- function GreetMe(name) { this.greeting = 'Hello '; this.name = name; this.speak = function() { console.log(this.greeting + this.name); console.log(this); } }; var greetJohn = new GreetMe('John'); var greetJane = new GreetMe('Jane'); greetJohn.speak(); greetJane.speak();
In the example above, both the
greetJohn
andgreetJane
variables are assigned a unique object returned by theGreetMe
constructor function. Therefore,this
inside of thespeak
method points to the uniqueGreetMe
object instance stored in the variable on which thespeak
method is being called. This is evident by looking at thename
property on theGreetMe
object.// Constructor Function Prototype Method // ------------------------------------- GreetMe.prototype.sayGoodbye = function() { console.log('Goodbye ' + this.name); console.log(this); }; greetJohn.sayGoodbye(); greetJane.sayGoodbye();
This example is similar to the previous. The difference is that instead of a method being called that exists directly on the object instance, the method is called from the constructor function’s prototype. However, the context of
this
does not change ‐ it still points to the uniqueGreetMe
object stored in the variable on which thesayGoodbye
method is being called. -
Whenever JavaScript’s
call
orapply
method is used,this
is explicitly defined.// Using call/apply // ---------------- greetJohn.sayGoodbye.call(greetJane); greetJane.sayGoodbye.apply(greetJohn);
JavaScript’s
call
andapply
methods allow you to execute a function in a different context. The first argument passed to either of these methods explicitly sets whatthis
points to. Becausecall
andapply
are explicit, they present the clearest case of whatthis
points to. This is evident by looking at thename
property logged to the console by each invocation of thesayGoodbye
method.
Hey John, you say:
“The difference is that instead of a method being called that exists directly on the object instance, the method is called from the constructor function’s prototype.”
I don’t think that this is the case, since the constructor function’s prototype is actually the function prototype.
The “prototype” property points to the prototype of the instantiated object, but it is not a prototype of the constructor function.
Otherwise, great article!
Hey Ivan,
Thanks for the comment. Drrrrp. Yeah, that merits some correction. Thanks for the catch :-).
I’m sure at the time I was trying to convey that the method does not exist directly on the object – being replicated on each instance. Rather, it is shared across all instances via the prototype.
For anyone seeing this comment who is a bit confused about prototypes, have a look at the first couple slides here: https://john-dugan.com/wp-content/uploads/2015/04/oloo-slides.pdf
Can you answer me for this?
Write a program called PNWord which prints “ONE”,”TWO”,”THREE”,”FOUR”,”FIVE”,”SIX”,”SEVEN”,”EIGHT”,”NINE”,”OTHER” if the int variable “number” is 1,2,…,9, or other respectively.
Output- 4=FOUR
Sorry, I don’t understand your question. :-/
hey everybody