JavaScript Binding `this` and arguments


Example

5.1

When you take a reference to a method (a property which is a function) in JavaScript, it usually doesn't remember the object it was originally attached to. If the method needs to refer to that object as this it won't be able to, and calling it will probably cause a crash.

You can use the .bind() method on a function to create a wrapper that includes the value of this and any number of leading arguments.

var monitor = {
  threshold: 5,
  check: function(value) {
    if (value > this.threshold) {
      this.display("Value is too high!");
    }
  },
  display(message) {
    alert(message);
  }
};

monitor.check(7); // The value of `this` is implied by the method call syntax.


var badCheck = monitor.check;
badCheck(15); // The value of `this` is window object and this.threshold is undefined, so value > this.threshold is false

var check = monitor.check.bind(monitor);
check(15); // This value of `this` was explicitly bound, the function works.

var check8 = monitor.check.bind(monitor, 8);
check8(); // We also bound the argument to `8` here. It can't be re-specified.

When not in strict mode, a function uses the global object (window in the browser) as this, unless the function is called as a method, bound, or called with the method .call syntax.

window.x = 12; 

function example() {
  return this.x;
}

console.log(example()); // 12

In strict mode this is undefined by default

window.x = 12; 
    
function example() {
  "use strict";
  return this.x;
}

console.log(example()); // Uncaught TypeError: Cannot read property 'x' of undefined(…)
7

Bind Operator

The double colon bind operator can be used as a shortened syntax for the concept explained above:

var log = console.log.bind(console); // long version
const log = ::console.log; // short version

foo.bar.call(foo); // long version
foo::bar(); // short version

foo.bar.call(foo, arg1, arg2, arg3); // long version
foo::bar(arg1, arg2, arg3); // short version

foo.bar.apply(foo, args); // long version
foo::bar(...args); // short version

This syntax allows you to write normally, without worrying about binding this everywhere.

Binding console functions to variables

var log = console.log.bind(console);

Usage:

log('one', '2', 3, [4], {5: 5});

Output:

one 2 3 [4] Object {5: 5}

Why would you do that?

One use case can be when you have custom logger and you want to decide on runtime which one to use.

var logger = require('appLogger');

var log = logToServer ? logger.log : console.log.bind(console);