Menu

Object-oriented Programming in JavaScript (Part 2)

First published on: 8 May 2018

‘this’ in JavaScript

In the first part of the series, we saw how object constructors could be used to create objects:

// Create Pet class.
function Pet (name, ageInYears) {
  this.name = name
  this.ageInYears = ageInYears
}

// Add a method to the Pet class.
Pet.prototype.notification = function () {
  return this.name + ' is ' + this.ageInYears + ' years old.'
}

// Create a new pet object.
var dog = new Pet('Dog', 4)

This is what happens when you call the notification function of dog:

// Returns 'Dog is 4 years old.'
console.log(dog.notification())

In this case, this.name is dog’s name ('Dog') and this.ageInYears is dog’s age in years (4). this basically refers to the newly created dog object, which is the object on the left of the dot.

Binding ‘this’ in JavaScript

One unexpected behavior of using this when a method is called, occurs when a called method is assigned to a variable. One solution would be to use the Function.prototype.bind() method (introduced in ES5) to return the expected value.

function bindExample () {
  this.value = 'unexpected'

  var exampleObject = {
    value: 'expected',
    getValue: function () {
      return this.value
    }
  }

  // Returns 'expected'.
  console.log(exampleObject.getValue())

  // Assign the 'getValue' method to
  //'notBoundMethod' variable.
  var notBoundMethod = exampleObject.getValue

  // Returns 'unexpected'. 'this.value' was supposed to be
  // 'expected' because of 'exampleObject.getValue'.
  console.log(notBoundMethod())

  // 'this' refers to the global/window
  // object in the browser (so it looks at:
  // this.value = 'unexpected')
  console.log(this)

  // One solution would be to use 'Function.prototype.bind()'.
  // Bind the method and assign to 'boundMethod' variable.
  var boundMethod = exampleObject.getValue.bind(exampleObject)

  // Returns 'expected'.
  console.log(boundMethod())
}
bindExample()

‘this’ in callbacks

A callback function is a function passed into another function as an argument, which is then called in an outer function.

The object constructor below, creates Pet objects where their age can be assigned. There is also a callback called growUp. If this is used within that it would refer to the global object or outer scope, which is not what we want. The code below will not increase the age of our pet fish over time.

function Pet () {
  this.age = 0
  setInterval(function growUp () {
    this.age++

    // 'this' refers to the (global) object
    // where 'new Pet()' is called.
    console.log(this)

    // Returns NaN, NaN, NaN ...
    console.log(this.age)
  }, 1000)
}
var fish = new Pet()

Binding this would fix this problem.

function Pet () {
  this.age = 0
  setInterval(function growUp () {
    this.age++
    // Now 'this' refers to 'fish'.
    console.log(this)

    // Returns 1, 2, 3 ...
    console.log(this.age)
  }.bind(this), 1000)
}
var fish = new Pet()

‘this’ in arrow functions

Arrow functions (introduced in ES6), do not have their own this. The this object of the outer scope is used. Just pretend that the arrow function does not exist when thinking about this with arrow functions. See the example below:

function Pet () {
  this.age = 0
  setInterval(() => {
    this.age++

    // Now 'this' refers to 'cat'.
    console.log(this)

    // Returns 1, 2, 3 ...
    console.log(this.age)
  }, 1000)
}
var cat = new Pet()

In the next part of the series, we will go over the class keyword (introduced in ES6):

Object-oriented Programming in JavaScript (Part 3)

Back:

Object-oriented Programming in JavaScript (Part 1)

The first version of this article was originally published on medium:

https://medium.com/@wlwlz/object-oriented-programming-in-javascript-part-2-41c7e5e58a0b

References: