Making sense out of Context in JavaScript

function sayHi(name) {
console.log('Hello, my name is ' + name);
}

Context Bindings

  1. Implicit Binding
  2. Explicit Binding
  3. new Binding
  4. window Binding

Implicit Binding

var Person = function (name, age) {
return {
name: name,
age: age,
sayHi: function () {
console.log('Hi, my name is '+ this.name);
}
};
};
var homer = new Person('Homer Simpson', 30);
homer.sayHi(); // "Hi, my name is Homer Simpson"
var homer = {
name: 'Homer Simpson',
age: 26,
sayHi: function () {
console.log('Hi, my name is ' + this.name);
},
daughter: {
name: 'Lisa Simpson',
sayName: function () {
console.log('Hi, my name is ' + this.name);
}
}
};
homer.sayHi(); // Hi, my name is Homer Simpson
homer.daughter.sayHi(); // Hi, my name is Lisa Simpson

Explicit Binding

function getCountryDetails() {
console.log(this.country + '\'s capital city is '+ this.capital + ' and as of ' + arguments[0] + ' the country has a population of ' + this.population + ' according to ' + arguments[1]);
}
var oz = {
country: 'Australia',
capital: 'Canberra',
population: '23M'
};
var nz = {
country: 'New Zealand',
capital: 'Wellington',
population: '4M'
};
var today = '30/12/2016';
var source = 'Wikipedia';
  • Function.prototype.call
  • Function.prototype.apply
  • Function.prototype.bind

i. Call

fun.call(thisArg[, arg1[, arg2[, ...]]])
  • The very first argument call takes in is the context you want to use.
  • Afterwards, you can pass in any number of comma-separated values which will be treated as arguments for the function fun.
getCountryDetails.call(nz, today, source);// "New Zealand's capital city is Wellington and as of 30/12/2016 the country has a population of 4M according to Wikipedia"

ii. Apply

fun.apply(thisArg, [argsArray])
  • First argument is the context we want to use.
  • Second argument is an array of values which are gonna be used as the arguments passed in to the function fun.
getCountryDetails.apply(oz, [today, source]);// "Australia's capital city is Canberra and as of 30/12/2016 the country has a population of 23M according to Wikipedia"

iii. Bind

var getOzDetails = getCountryDetails.bind(oz, today, source);// nothing happens just yet...getOzDetails(); // we need to manually run the resulting function// "Australia's capital city is Canberra and as of 30/12/2016 the country has a population of 23M according to Wikipedia"
Function.prototype.bind = function (context) {
var fn = this;
var outerArgs = [].slice.call(arguments, 1);

return function () {
var innerArgs = [].slice.call(arguments, 0);
fn.apply(context, [].concat(outterArgs, innerArgs));
};
};
var missingSource = getCountryDetails.bind(oz, today);
var missingAllArgs = getCountryDetails.bind(oz);
missingSource(source);
missingAllArgs(today, source);

Let’s recap:

  • call, apply and bind they all allow us to explicitly set the value of this when calling a function.
  • call and apply both invoke the bound function immediately.
  • bind doesn’t invoke the bound function immediately, rather returns a new function we can run later.
  • call and apply differ only in the format they take extra arguments in: use comma-separated values for call, array of values for apply.
  • bind takes extra arguments as comma-separated values, just as call does.

New Binding

var Dog = function (name, breed, color) {
// this = {} --> `this` equals to a brand new object
// being created by the `new` operator whenever the
// function gets instantiated.
this.name = name;
this.breed = breed;
this.color = color;
this.sayHi = function () {
console.log('My name is ' + this.name + ', woof woof!');
}
};
var puppy = new Animal('Axel', 'German Shepherd', 'Black');
puppy.sayHi();

Window Binding

function sayHi() {
console.log('Hi, my name is ' + this.name);
};
sayHi(); // undefined
window.name = 'Homer'; // might as well be `var name = 'Homer';`
sayHi(); // we now get "Hi, my name is Homer"
function sayAge() {
'use strict';
console.log(this.age);
};
sayAge(); // bummer! type error thrown ⚠️

ES6 Goodness: Arrow Functions

function () {
this.greeting = 'Good day mate';

// If we don’t bind this function, it'll echo out `undefined`
setTimeout(function () {
console.log(this.greeting);
}.bind(this));

// Binding here happens automagically using the parent scope
setTimeout(() => {
console.log(this.greeting);
});
}

--

--

--

Front End Developer 👨‍💻

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Federico Knüssel

Federico Knüssel

Front End Developer 👨‍💻

More from Medium

Asynchronous Code Execution in JavaScript

JS-14 — JavaScript for Programmers, Chapter10

4 Ways to Handle Async Operations in Javascript

4 Ways to Handle Async Operations in Javascript

Operators, Scope, and Functions.