Re-Realizing context

explicitly setting this

Jay GuravPublished on May 16, 2021
๐Ÿ• 2 min read.

Often when getting started into programming most seasonal developers struggle their way into understanding this (especially in functional languages) and get into all sort of troubles that even further messes up things, however โ€œthisโ€ becomes easy when they understand that this is all about the context of invoking a function rather than confusing yourself with from where it was declared(which is mostly the case in Object Oriented language).

It ainโ€™t what you donโ€™t know that gets you into trouble, Its what you know for sure that just ainโ€™t so -Mark Twain

If you find above terms difficult not to worry they are themselves a fully fledged topics to write an article or even a book to get into nitty-gritty details of this

Implicit Binding

Implicit binding is when the context of invoking this is internally, intentionally and automatically bound to something else. These are considered as default standards/rules of how this behaves, for example

this with a getter or setter is one such example of implicit binding, consider another example below

JS
function greet() {
// this === userDetails //true
console.log(`Hello ${this.fullName}!`) //Hello Jay Gurav!
}
const userDetails = {
fullName: "Jay Gurav",
greet,
}
userDetails.greet()

When a function is called as a method of an object, its this is set to the object the method is called on. So in the above example greet method on object userDetails has this internally bounded to the object which invokes the function as its method using . operator, so the this === userDetails would result to true in greet function when called using userDetails.greet(). It to important to note that only the last property matters, so something like below

JS
function greet() {
// this === userDetails //false
console.log(`Hello ${this.fullName}!`) //Hello John Doe!
}
const userDetails = {
fullName: "Jay Gurav",
greet,
}
const dummyUserDetails = {
fullName: "John Doe",
greet: userDetails.greet,
}
dummyUserDetails.greet()

Here even if the greet property on dummyUserDetails points to userDetails.greet the this here in this case would be dummyUserDetails and not userDetails. So always remember in case of objects this refers to the object on which the method is invoked.

Explicit binding

so as the title says to re-realize context or to explicitly set this to some another context of our wish, JavaScript provides us with three useful methods .bind(), .call() and .apply() available to all functions through Function.prototype object to do so.

So we can achieve something that we intended to do above as follows

JS
function greet() {
console.log(this === userDetails) //true
console.log(`Hello ${this.fullName}!`) //Hello Jay Gurav!
}
const userDetails = {
fullName: "Jay Gurav",
greet,
}
const dummyUserDetails = {
fullName: "John Doe",
greet: greet.bind(userDetails),
}
dummyUserDetails.greet()

Here we explicitly say that we want to bind the method (not function) greet on dummyUserDetails with the context of userDetails.

call

The call method on Function.prototype object call a function with the provided context assigned to this, and the following arguments passed to the function as its arguments list.

Function.prototype.call ( thisArg, ...args )

The thisArg value is passed without modification as this value to the calling function. However it is important to note that when undefined or null is passed as thisArg then it is replaced with the global object and if the function is an arrow function then the thisArg will be ignored by the function.

for example

JS
function log(ps) {
console.log(`${ps} ${this.name}`)
}
const product = {
name: "cheese",
}
const myPet = {
name: "Bruno",
}
log.call(product, "Yummy") //Yummy cheese.
log.call(myPet, "๐Ÿถ") // ๐Ÿถ Bruno

apply

The apply method on Function.prototype object calls a function with the provided context assigned to this, and the array/array-like-object passed as the second argument that is passed to the calling function.

Function.prototype.apply ( thisArg, argArray )

Note that the syntax of .call() and .apply is almost identical , the fundamental difference is that .call() accepts an argument list while .apply accepts a single array of argument.

so in the above example we could be doing something like log.call(myPet, ["๐Ÿถ", "๐Ÿฐ"])

bind

The .bind() method on Function.prototype object creates a new function that when call has its this set to the provided context and the following arguments passed to the function as its arguments list.

Function.prototype.bind ( thisArg, ...args )

consider this below example

JS
const user = {
name: "John Doe",
age: 42,
getUser: function (){
return {name: this.name, age: this.age};
}
}
const globalContextUser = user.getUser;
getUser() //{ name: undefined, age: undefined } as it is invoked from global scope
const boundedUser.bind(user); //this is set to user, returns a new function
boundedUser() //{ name: "John Doe", age: 42 }

๐Ÿ“š Further reading and resources

Get in touch

Hey, have any suggestions, questions or concerns, Feel free toMail me. You can also find me onTwitter,GithubandLinkedin. Help me make this better drop me a message and I'll get back to you soon Thanks!๐ŸŽ‰

๐Ÿ“ฎ Share this post