What is this in javascript?
this keyword refers to an object, the object that is executing the current part of our Javascript code.
Why is it so complicated to understand?
We might feel overwhelmed as there are quite a number of ways to manipulate this by providing it a different context.
this binding has nothing to do with where a function is declared but it has everything to do with how a function is invoked.
There are 4 main Rules which we can make use of, to determine what this in your code represents.
E.D.I.N - Stands for Explicit binding, Default binding, Implicit binding and new Binding.
(There is no EDIN concept, its just my way to remember these concepts)
Rule 1.Implicit Binding:
Implicit Binding is achieved when the function that is executed is called with a context.
Example:
const obj = {
name: 'Dev',
getName : function() {
console.log(this.name);
}
}
obj.getName(); // Dev
obj.getName()
- Here we call the
getName()function of the objectobjwithobjas the context. - Since
objhasnameproperty,this.namewould give out dev as the output.
What if your function is nested within objects?
Example:
const obj = {
name: 'Dev Child',
getName : function() {
console.log(this.name);
}
}
const parentObj = {
childObj: obj,
name: 'Dev Parent'
};
parentObj.childObj.getName(); // Dev Child
- The last level parent before any function call is the context for that function.
- In our case
objis thethisforgetName()function.
The Fat Arrow function catch:
var name = 'Global Dev';
const obj = {
name: 'Local Dev',
getName : () => {
console.log(this.name);
}
};
obj.getName() // Global Dev π π π
- The problem here is
thisbinding has been done for thegetNamearrow function and it takes Lexicalthiswhich is Gloabl in this case. - So calling the function with impicit binding takes lesser priority than Arrow function.
2.Default Binding:
Default binding is whenever the function is called without any context.
A common mistake occurs while destructuring a function from an object which has this context in it.
var name = 'Global Dev';
const obj = {
name: 'Local Dev',
getName : function() {
console.log(this.name);
}
};
const { getName } = obj;
getName(); // Global Dev π€π€π€
- Here we have destructured the
getNamefunction out of the objectobj. - Then, we have called it without any context
- It means the function execution here is happening with Global context.
- So while execution if it encounters any
thisin the code that will try to resolve its value by checking window object. - We have 'Global Dev' value assigned to
nameinwindowobject sothis.nameresolved towindow.namewhich is 'Global Dev'. - Note: The same would have resulted in returning
undefinedinstrictmode.
How to Overcome this?
By using Explicit binding
3.Explicit Binding:
Explicit binding is a process of specifying what this object is, while calling the function. It is usually done with the help of the famous Js trio call, apply and bind.
var name = 'Global Dev';
const obj = {
name: 'Local Dev',
getName: function() {
console.log(this.name);
};
};
const { getName } = obj;
const newContext = {
name: 'New Dev'
};
// Explicit binding takes priority over Default binding
getName.call(newContext); // New Dev
// Explicit binding takes priority over Implicit binding
obj.getName.call(newContext); // New Dev
It is clear from the above that, Explicit bindings take priority over Implicit or Default Binding.
But does it have a Higher priority than Arrow function's this binding.
No!

var name = 'Global Dev';
const obj = {
name: 'Local Dev',
getName: () => {
console.log(this.name);
}
};
const newContext = {
name: 'New Dev'
};
//Arrow function's bind took priority over Explicit binding.
obj.getName.call(newContext); // Global Dev
Priority Ordering:
Arrow Function > Explicit Binding > Implicit Binding > Default Binding
4.new Binding:
If the function is called with new operator in the prefix then the newly constructed object is the this reference here.
function MyName() {
this.name = "Local Dev";
}
MyName.prototype.getName = function() {
console.log(this.name);
}
// `new` binding
const name_instance = new MyName();
console.log(name_instance.name); // Local Dev
// Implicit Binding
name_instance.getName(); // Local Dev
- Here we have defined our instance variable
name_instancewhich is formed fromnewopertor operating on factory functionMyName. - All references to
thisinMyNamefunction refers to the newly created object instancename_instance
All our Rules from 1 to 3 applied to this instance (name_instance):
// Default Binding
var name = "Global Dev"
const {getName} = name_instance;
getName(); // Global Dev
// Implicit Binding
name_instance.getName(); // Local Dev
// Explicit Binding
name_instance.getName.call({ name: 'New Dev'}); // New Dev
// Arrow Binding
MyName.prototype.get_Arrow_Name = () => {
console.log(this.name);
}
name_instance.get_Arrow_Name(); // Global Dev
React Classes:
class App extends React.Component {
constructor() {
this.handle_three = this.handle_three.bind(this);
}
handle_one() {
console.log(this);
}
handle_two = () => {
console.log(this);
}
handle_three() {
console.log(this);
}
render() {
return (
<React.Fragment>
{/* Default binding */}
<div onClick={this.handle_one}></div>
{/* Arrow Function */}
<div onClick={this.handle_two}></div>
{/* Expicit Binding at constructor*/}
<div onClick={this.handle_three}></div>
</React.Fragment>
)
}
}
- Handlers on JSX elements will call the function declared.
-
handle_oneattachment results in calling the function with no context(Default binding). This results inundefinedbecause React ensures Default binding results inundefinedrather than a Global. -
handle_twoattachment results in calling the function with the newly created Intsance's (Current App Class's instance's) context. -
handle_threeattachment results in explicit binding to provide value forthisat the constructor.
Hope you guys have Enjoyed this Article π
Reference: Kyle Simpson's this & Object Prototypes
Thats all Folks!!!



Top comments (1)
Very informative post! I just wanted to mention that in the case of events handled by
addEventListener, if you pass an object that implements#handleEvent, it will be called witheventas its argument, and it will be implicitly bound to the object passed in toaddEventListener. If you call any other functions on the object within the body ofhandleEvent, they will also be implicitly bound to the object, too! This saves memory by preventing you from having to use#bindor the arrow syntax for those functions, which both create copies of the function in question,. In circumstances where you have a large number of objects, this can save you a ton of overhead!