Ads Top

What's this in JavaScript - the web stop

If you work in JavaScript or any other programming language, you may have used this. However, this in JavaScript works differently than in other languages. There have been so many misconceptions about the use of this leading to its improper use and thus, causing errors. In this post, we'll try to understand the better use of this.

Jim likes coffee. Jim likes tea as well.  // Without the use of "Pronoun"
Jim likes coffee. He likes tea as well.   // With the use of "Pronoun"

As in the second sentence, the introduction of "He" as a pronoun makes the sentence look better than the first one, this keyword is also used in writing neat and elegant code.


Consider the following code:


function username(person) {
 return person.name.toUpperCase();
}

function greeting(person) {
 var salutation = "Hello" + " " + username(person);
 console.log(salutation);
}

var jack = {
 name : "Jack"
}

var jill = {
 name : "Jill"
}

greeting(jack); //Hello JACK
greeting(jill); //Hello JILL


and now the following code using this keyword instead of passing person object to both username and greeting functions.


function username() {
 return this.name.toUpperCase();
}

function greeting() {
 var salutation = "Hello" + " " + username.call(this);
 console.log(salutation);
}

var jack = {
 name : "Jack"
}

var jill = {
 name : "Jill"
}

greeting.call(jack); //Hello JACK
greeting.call(jill); //Hello JILL

The difference between the above two code snippets is that this has allowed both username and greeting functions to reuse the person object without creating a separate function for each object. We didn't define person object separately for username and greeting functions. Thus, this keyword has made our code cleaner and easier to re-use by indirectly passing along object reference.

What matters for this ?

The only thing matters for this binding is where the function is invoked instead of where and how it is declared. The appropriate use of this can be determined by nature of invoking a function while it is being executed.


This is the most common misconception about this in JavaScript. We'll look into some scenarios where the value of this is determined by how the function is called.


Global Context

function username() {
 console.log(this.name);
}

var name = "Jill";

username(); //Jill


In the above snippet of code, function username is invoked in an ordinary manner which is a standalone function invocation. By default, this binding will point to the global object which in this case is globally defined name. Hence, this is bound to name.

Object method


function username() {
 console.log(this.name);
}

var person = {
 name : "Jill",
 username : username
}

person.username(); //Jill

Again, it is all about how the function is invoked. This time, it is invoked using Object reference. username is defined twice but it is not relevant when choosing how to bind this. ( : It's not about how the function is declared, it is about how it is called).

However, person object "owns" the username function reference at the time the function is called. In this scenario, object should be used for the function call's this binding. Hence, this.name is bound to person.name

Without reference in an object

In the above example, we saw that function was declared inside an object as well. Hence, the function reference was called using object. What if in a typical scenario, we don't have a function reference on an object but we still want to force a function call using that object for this binding?

Here come to play call, apply and bind

call


function username() {
 console.log(this.name);
}

var person = {
 name : "Jill",
}

username.call(person); //Jill

username.call() forces this to be person explicitly without having username function reference on personobject.

apply


function person(name, age) {
  console.log("Our first User is " + name + ", a " + this.gender + " of " + age + " years old");
}

var firstUser = {
 gender : "female",
}

person.apply(firstUser, ["Jill", 25]); //Our first User is Jill, a female of 25 years old

person.apply works the same way as person.call does. Both differ in number of arguments each can supply.The main difference is that apply lets you invoke the function with arguments as an array; call requires the parameters be listed explicitly using commas.

Their syntaxes differ as in :

function.apply(valueOfThis, arrayOfArgs);
person.apply(firstUser, [Jill, 25]);


function.call(valueOfThis, arg1, arg2, ...);
username.call(person);




bind

bind() creates a new function and in the new function this is permanently bound to the first argument of the bind function. Unlike call() and apply(), bind() is not invoked immediately and rather creates a new function with a given this value and returns that function without executing it.


function add(a) {
 console.log(this.b, a);
 return this.b + a;
}

var myNumber = {
 b : 4
}

var something = add.bind(myNumber);

var myValue = something(3); //4 3
console.log(myValue); // 7


this lexically

In ES6, the fat arrow functions (using fat arrow operator =>) use lexical scoping for binding this to the enclosing function.In global code, it will be set to the global context.


function name(){
 return (firstName) => {
 console.log(this.firstName);
 };
}

var person1 = {
  firstName : "Jill"
}

var person2 = {
 firstName : "Jack"
}

var personName = name.call(person1);
personName.call(person2); //Jill


In the above code snippet, the fat arrow operator in the function name captures this at the time function is invoked. Since name has this bound to person1, so personName will also be bound to person1. It is important to remember that lexical binding of fat arrow function cannot be overridden. It is a replacement of var self = this; from ES versions existings before ES6.


TL;DR

  • this keyword is used to make code look cleaner, elegant and easier to reuse.
  • this is a binding whose reference depends entirely on where the function is invoked rather than where it is declared.
  • call() is used when a function is invoked with its first argument being the value of this and other arguments can be comma separated list.
  • apply() is used when a function is invoked with its first argument being the value of this and other arguments as an array.
  • bind() creates another function with its first argument being the value of this and returns the function without executing it.
  • Fat arrow functions introduced in ES6 replaced var self = this; and use lexical scoping for this binding.

No comments:

Powered by Blogger.