What is this Keyword?
The this keyword can be confusing to even experienced JavaScript programmers. In other programming languages, this is used to refer to the current instance of an object created from a class. In JavaScript, the this keyword can often appear to work the same way—right up until the moment a change breaks the application and undefined values start to appear.
To demonstrate, I used the fat arrow syntax.
The method uses the same console.log statement, but when the change is saved and the code is executed, the output shows undefined values, like this:
Understanding why this happens and being able to fix the problem requires taking a step back and examining what the this keyword really does in JavaScript.
Understanding the this Keyword in Stand-Alone Functions
The this keyword can be used in any function, even when that function isn’t used as a method
The writeMessage function reads a property named greeting from this in one of the expressions in the template string passed to the console.log method. The this keyword doesn’t appear again in the listing, but when the code is saved and executed, the following output is produced:
JavaScript defines a global object, which can be assigned values that are available throughout an application. The global object is used to provide access to the essential features in the execution environment, such as the document object in browsers that allows interaction with the Document Object Model API.
Values assigned names without using any keyword or var keyword are assigned to the global object. The statement that assigns the string value Hello creates a variable in the global scope. When the function is executed, this is assigned the global object, so reading this.greeting returns the string value Hello, explaining the output produced by the application.
The standard way to invoke a function is to use parentheses that contain arguments, but in JavaScript, this is a convenience syntax that is translated into the statement.
As explained earlier, functions are objects, which means they define methods, including the call method. It is this method that is used to invoke a function behind the scenes. The first argument to the call method is the value for this, which is set to the global object. This is the reason that this can be used in any function and why it returns the global object by default.
The new statement uses the call method directly and sets the this value to the global object, with the same result as the conventional function call before it, which can be seen in the following output produced by the code when executed:
The name of the global object changes based on the execution environment. In code executed by Node. js, global is used, but window or self may be required in browsers. At the time of writing, there is a proposal to standardize the name global, but it has yet to be adopted universally.
UNDERSTANDING THE EFFECT OF STRICT MODE
JavaScript supports strict mode, which disables or restricts features that have historically caused poor-quality software or that prevent the runtime from executing code efficiently. When strict mode is enabled, the default value for this is undefined to prevent accidental use of the global object, and values with global scope must be explicitly defined as properties on the global object.
See JavaScript Reference Strictmode for details. The TypeScript compiler provides a feature for automatically enabling strict mode in the JavaScript code it generates.
Understanding this in Methods
When a function is invoked as an object’s method, this is set to the object.
When the function is invoked via the object, the statement that invokes the function is equivalent to using the call method with the object as the first argument, like this:
Care is required because this is set differently if the function is accessed outside of its object, which can happen if the function is assigned to a variable.
Functions can be used like any other value, including assigning them to variables outside of the object in which they were defined, as shown in the listing. If the function is invoked through the variable, then this will be set to the global object. This often causes problems when functions are used as arguments to other methods or as callbacks to handle events, and the effect is that the same function will behave differently based on how it is invoked, as shown in the output produced by the code
Changing the Behavior of the this Keyword
One way to control the this value is to invoke functions using the call method, but this is awkward and must be done every time the function is invoked. A more reliable method is to use the function’s bind method, which is used to set the value for this regardless of how the function is invoked.
The bind method returns a new function that will have a persistent value for this when it is invoked. The function returned by the bind method is used to replace the original method, ensuring consistency when the writeMessage method is invoked. Using bind is awkward because the reference to the object isn’t available until after it has been created, which leads to a two-step process of creating the object and then calling bind to replace each of the methods for which a consistent this value is required. This code produces the following output:
The value of this is always set to myObject, even when the writeMessage function is invoked as a standalone function.
Understanding this in Arrow Functions
To add to the complexity of this, arrow functions don’t work in the same way as regular functions. Arrow functions don’t have their own this value and inherit the closest value of this they can find when they are executed. To demonstrate how this works.
The getWriter function is a regular function that returns an arrow function as its result. When the arrow function returned by getWriter is invoked, it works its way up its scope until it locates a value for this. As a consequence, the way that the getWriter function is invoked determines the value of this for the arrow function. Here are the first two statements that invoke the functions:
These two statements can be combined as follows:
The combined statement is a little harder to read, but it helps emphasize that the value of this is based on how a function is invoked. The getWriter method is invoked through myObject and means that the value of this will be set to myObject. When the arrow function is invoked, it finds a value of this from the getWriter function. The result is that when the getWriter method is invoked through myObject, the value of this in the arrow function will be myObject, and the this.greeting expression in the template string will be Hi, there.
The statements in the second set treat getWriter as a stand-alone function, so this will be set to the global object. When the arrow function is invoked, the this.greeting expression will be Hello. This code produces the following output, confirming the this value in each case:
Returning to the Original Problem
I started this section by redefining a function in the arrow syntax and showing that it behaved differently, producing undefined in its output. Here is the object and its function:
The behavior changed because arrow functions don’t have their own this value, and the arrow function isn’t enclosed by a regular function that can provide one. To resolve the issue and be sure that the results will be consistent, I must return to a regular function and use the bind method to fix the this value.
With these changes, the value of this for the writeDetails method will be its enclosing object, regardless of how it is invoked.
About Anas Aqeel
I’m currently working Frontend Development having an experience of building Web applications with JavaScript / React-JS / Node-JS and some other cool libraries and frameworks. I’m currently learning web3 technologies such as Solidity, Ether-JS and web3.