Many times this
keyword in JavaScript can be confused if it is not understood correctly. In this article, I will show you how this
works with some code examples and how its value is assigned in a different context in JavaScript. There are different scenarios where this
can change its value:
- `this` in a global context, function invocation
- `this` in an object constructor
- `this` in an object method.
- `this` with arrow function (=>)
But wait before jumping to the examples we just mentioned context so what is it in JavaScript? The context in JavaScript is always the value of this
that is determined during the execution code. To clearly understand let's go now with code examples and see how it works on each scenario.
console.log("What is 'this' value?", this) // Window
function simpleFunction () {
console.log("What is the value of this inside function?", this) // Window
}
simpleFunction()
From the code example 1 this
refers to the global object which is determined from the execution context and wherein the browser is the global object (window). Similarly, when invoking the function this
inside that function refers to the global object. But what this
refers inside constructor function? We see this in the code example 2 as below.
function Person(name, lastName) {
this.name = name;
this.lastName = lastName;
this.displayName = function() {
console.log(`Your name ${this.name} and lastName
${this.lastName}`)
}
}
let person = new Person('George', 'Superman')
person.displayName() // George Superman
As we see from the code above we create a construction function Person and then we invoke a new instance object george. this
value, in this case, refers to the newly created object.
let greetings = {
word: 'Hello',
printGreeting: function(){
console.log("What 'this' refers to inside object method? ",
this.word) // "this" in object refers to the object itself- greetings
}
}
greetings.printGreeting()
From code example 3 above we created an object which has a property and method printGreeting. We are calling the property name inside the method with this
which its value refers to the object itself.
We saw from the code examples above that this
value inside a function refers to the global object and inside of an object method refers to the object itself but what about if we want to invoke an object method inside another function and reference this
. What will be the value of this
in this context? Let's see with the code example 4 and where we will run it with strict mode as below
"use strict"
let person = {
firstName: 'George',
}
function printName(greeting) {
console.log(greeting + this.firstName)
}
printName('hello') // Uncaught TypeError: Cannot read property 'firstName' of undefined
After running the code we see that we get an error because JavaScript interpret does not understand object property this.firstName because this
value inside a function is set during the execution context. But, how to overcome this issue? JavaScript functions are a special type of objects which contains methods call(), apply() and bind().
call(), apply() and bind()
These methods are inherited by all functions in order to get the value of this
in any desired context. The differences between these function methods are that call() method requires parameters as a comma-separated and apply() method in the form of the array list and are executed immediately whereas bind() method can be executed later in any desired context. The code example 5 below shows how we can use these methods and set this
in any desired context.
let person = {
firstName: 'George',
}
function printName(greeting) {
console.log(greeting + this.firstName);
}
printName.call(person, 'Hello') // Hello George
printName.apply(person, ['Hello there']) // Hello there George
let executeLater = printName.bind(person)
executeLater() // George
this
with arrow function =>
With ECMAScript 2015 (ES6) arrow function was introduced as a new feature in the world of JavaScript. There are a lot of benefits on using arrow functions which brings shorter function syntax to no need on binding this
. With the use of arrow function this
is bounded lexically in the enclosing context. Let's see this in action with code example to make it clear.
let greetings = {
word: 'Hello',
printGreeting(){
console.log(this.word) // Hello
})
}
}
If we go back to the previous code example 2 we saw that this
inside object refers to the object itself but what if we are required that our greeting to be displayed after 1 second. Then to get the required result we need to modify the code as below
let greetings = {
word: 'Hello',
printGreeting(){
window.setTimeout(function () {
console.log(this.word)
}, 1000) // we can set bind(this)
}
}
greetings.printGreeting() // undefined
We see that after executing the method printGreeting() we get undefined because the setTimout() function invocation sets this
context to the global object. However, here to achieve the result we can use bind() method as we saw previously or we can create a closure just before the setTimeout() function with self=this but we don't need to do this as we can achieve the desired result with the use of arrow function
let greetings = {
word: 'Hello',
printGreeting(){
window.setTimeout(() => {
console.log(this.word)
}, 1000)
}
}
greetings.printGreeting() // Hello
Now as the result on the console we will get greeting hello because with use of arrow function "this" is bound to the enclosing context and thus our "greetings" object.
That's it! :)
Hopefully, you find interesting this article and will help you in understanding this
in JavaScript and its value in a different context.
Top comments (9)
Thanks for good article!
Can you explain more why this
code returns exception?
Just context of the
printName
function refers towindow
object, as I understand, and because of this output should behelloundefined
?BTW, it would work
Hello guys
Thanks for pointing this out and you are both right, by default it should output hello undefined but here I run the code in a strict mode which was my mistake I forgot to mention it(now edited and corrected ). So running this in strict mode it will throw an exception and output with TypeError :)
Nice article. Just wanted to point out that while all you said works alright on the frontend, on Node things get more complex.
For example, your very first sample code fails: runkit.com/dalmo3/whatisthis
I used to think it was all the same, then yesterday struggled for a couple of hours before finding out about the module wrapper, exports, global etc.
Hello Dalmo,
That's correct in a node.js environment running script code it is essential to have module wrapper with export.
Hey Naim, use const 🙃
Honourable mention:
globalThis
Thank you Adam! 😃
Thanks for good article! 'This' it is not intuitive.
Thank you! 😃