Coming to Javascript from languages like Ruby can be difficult. As Ruby developers, we get a lot for free. Things like the Enumerable module and symbol to proc can spoil us Ruby developers. One especially confusing language feature that changes from Ruby to Javascript is the concept of this.

In Ruby, methods are implicitly bound to the current object:

class User
  def calculate
    # self is an instance of User
    [1,2,3,4,5].map do |num|
      # self is an instance of User
      self.do_something
    end
  end
end

In Javascript however, method/function binding is not implicit. Note that in Javascript, this is a synonym for Ruby’s self

// es6 class syntax
class User {
  calculate() {
    // ‘this’ is an instance of Window if in a web browser
    [1,2,3,4,5].map(function(num, index) {
      // ‘this’ is an instance of Window
      this.doSomething()
    })
  }
}

user = new User
user.calculate()

In order to maintain the same context of this in Javascript, we have to manually set it using the bind function:

class User {
  calculate() {
    // ‘this’ is an instance of User
    [1,2,3,4,5].map(function(num, index) {
      // ‘this’ is still an instance of Window
      this.doSomething()
    })
  }
}

user = new User
// We manually bind the context of ‘this’ to be the ‘user’ variable
user.calculate.bind(user)()

The above code may look a bit strange. The second set of parentheses is just calling the function after it has been bound.

You can find a more in depth explanation of what bind does in the awesome Mozilla documentation. Here’s a quick explanation from those docs:

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

We still have one more problem: the loop within the calculate function is still not bound to the right context. We want calculate to also refer to the user object instead of the window. The solution is simply another call to bind after the loop.

class User {
  calculate() {
    // ‘this’ is an instance of User
    [1,2,3,4,5].map(function(num, index) {
      // ‘this’ is now an instance of User
      this.doSomething()
    }).bind(this)
  }
}

user = new User
user.calculate.bind(user)()

A simple way I like to think about this is that any time variable scope changes, like within a loop, you should pass in the parent context.

Looking ahead

Earlier last year ECMAScript2015, or ES6 as it’s most commonly referred to, was released. With it came a feature called arrow functions. Arrow functions automatically bind this to the parent context:

class User {
  calculate() {
    // ‘this’ is an instance of User
    [1,2,3,4,5].map((num, index) => {
      // ‘this’ is an instance of User
      this.doSomething()
    })
  }
}

user = new User
user.calculate.bind(user)()

Unfortunately, arrow functions are always anonymous, so we can’t write our class like this:

class User {
  calculate() => {
    // ‘this’ is an instance of User
    [1,2,3,4,5].map((num, index) => {
      // ‘this’ is an instance of User
      this.doSomething()
    })
  }
}

user = new User
user.calculate()

I don’t love these confusing parts about Javascript, but there is no sense in ignoring them. Javascript is here to stay, and being armed with knowledge of the more annoying language features has saved me many headaches.