All Articles

What is this(WIP?

How to use this in Javascript

Many developers strugle to use this because works different like other languages. Due to this misundertanding we end up to write a huge amount of duplicated code in order to fix some issues related to this like sharing data across components or when nested functions needs to access function/data from parent functions like in callback events for example. Understanding this will help you to modularize javascript into functions, avoid problems with this is undefined as we will see later on.

Let’s start with the basic. We will cover how it works in:

  • functions
  • object literals
  • constructors
  • classes ES6
  • call, apply and bind
  • arrow functions

If you want to see more complex structures in order understand the common issues in complex javascript code you can my next article I am working on.

The value of this is determined by how a function is called (runtime binding).

Functions

The context of this in function represent everything assigned in this inner function or outside (for browser) or by setting global for nodejs.

browser

var b = 'cool'; 
function calling(){
	this.a = 'awesome';
  console.log(this.a);
  console.log(window.a);
  console.log(this.b);
}

calling(); 

output

awesome
cool
cool

nodejs

global.b = 'cool';
function calling(){
	this.a = 'awesome';
  console.log(this.a);
  console.log(global.b);
  console.log(this.b);
}

calling();

output

awesome
cool
cool

The first example, all the variables are availabe on window for browswer, while for nodejs is available in global variable. Note that for nodejs, if we set b at var it wouldn’t be availabe at global.

Object Literals

In object literals this always belongs to the object where it has been created.

var MyComponent = {
  name:'This is a component',
  display:function(){
    console.log(this.name);
 }
}
MyComponent.display();

output

This is a component

Constructor

When we create a instance, the context this moves to the context of the object created, similar to Object Literal.

function Person(name){
  this.name = name;
  this.displayName = function(){
    console.log(this.name);
  }
}
var p = new Person('Alan');
p.displayName();

output

Alan

Classes ES6

We can do the example above by using classes in ES6.

class Person{
  constructor(name){
    this.name = name;
  }
  displayName(){
    console.log(this.name);
  }
}
var p = new Person('Alan');
p.displayName();
// Alan

call, apply and bind

The methods call, apply and bind change the context of this. The only differece is the way they are invoked. call has multi args, while apply has array as argument. bind, changes the context of this and can keep some arguments.

call

var person = {
  fullName: function(city, country) {
    return this.firstName + " " + this.lastName + "," + city + "," + country;
  }
}
var person1 = {
  firstName:"John",
  lastName: "Doe"
}
var fullName = person.fullName.call(person1, "Oslo", "Norway");
console.log(fullName);

output

John Doe,Oslo,Norway

The variable person1 is the context this. Oslo and Norway are the arguments city and country respectively.

apply

var person = {
  fullName: function(city, country) {
    return this.firstName + " " + this.lastName + "," + city + "," + country;
  }
}
var person1 = {
  firstName:"John",
  lastName: "Doe"
}
var fullName = person.fullName.apply(person1, ["Oslo", "Norway"]);
console.log(fullName);

output

John Doe,Oslo,Norway

The variable person1 is the context this. Oslo and Norway are the arguments city and country respectively.

bind

function getFirstName(){
  return this.firstName;
}

var person1 = {
  firstName: 'Patrick'
}

var person2 = {
  firstName: 'Mary'
}

var getFirstName_1 = getFirstName.bind(person1);
var getFirstName_2 = getFirstName.bind(person2);

console.log(getFirstName_1())
console.log(getFirstName_2())

output

Patrick
Mary

You can also use bind to send arguments.

function getFirstName(secondName,country){
  return this.firstName+' '+secondName+' and lives in ';
}

var person1 = {
  firstName: 'Patrick'
}

var getFirstNameFull = getFirstName.bind(person1,'Oconnel');

console.log(getFirstNameFull('Ireland'))

output

Patrick Oconnel and lives in Ireland

Note that while call/apply invokes the function, bind only store the function with its context and arguments. You can see on my next article what scenarios they are very helpful.