Intro
In this article, we will discuss three of the most important concepts in JavaScript:
call
, bind
and apply
along with their pollyfils. We will see how these concepts can be used to write better code.Call
The
call()
method is used to call a function with a given this
value and arguments provided individually.For example, consider the following code:
const personDetails = { name: 'Jane', hello(age) { console.log("Hello " this.name + '! age:' + age); }, }; console.log(personDetails.hello("21")); // Hello, Jane! age: 21
But what if we wanted to call the
hello()
function with a different this
value, in other words with a different object / context. We can use the call()
method to do thisconst personDetails = { name: 'Jane', hello(age) { console.log("Hello " this.name + '! age:' + age); }, }; const newPersonDetails = { name: 'John', }; console.log(personDetails.hello.call(newPersonDetails, "26")); // Hello, John! age: 26
As we can see, the
call()
method takes two arguments: the first argument is the value of this
, and the second argument is the age that should be used in the hello()
function.Let’s take a look at some more examples to understand this better.
function Product(name, price) { this.name = name; this.price = price; } function Food(name, price) { Product.call(this, name, price); this.category = 'food'; } function Toy(name, price) { Product.call(this, name, price); this.category = 'toy'; } const cheese = new Food('feta', 5); const fun = new Toy('robot', 40);
pollyfill for call
This pollyfil for bind is fairly simple, its a function with takes the context or
this
value and the arguments the function should be called with and executes the function Function.prototype.myCall = function (obj = {}, ...args) { if (typeof this !== 'function') { throw new Error(this + ' cannot be bound as this is not callable'); } obj.fn = this; obj.fn(...args); // call the function with the args and the context provided };
Bind
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.For example, consider the following code:
const personDetails = { name: 'Jane', hello(age) { console.log("Hello " this.name + '! age:' + age); }, }; const newPersonDetails = { name: 'John', }; const newPersonDetailsHello = personDetails.hello.bind(newPersonDetails, "26") console.log(newPersonDetailsHello()) // Hello, John! age: 26
Lets take a look at a few more example to understand better
this.x = 9; // 'this' refers to the global object (e.g. 'window') in non-strict mode const module = { x: 81, getX() { return this.x; }, }; module.getX(); // returns 81 const retrieveX = module.getX; retrieveX(); // returns 9; the function gets invoked at the global scope // Create a new function with 'this' bound to module // New programmers might confuse the // global variable 'x' with module's property 'x' const boundGetX = retrieveX.bind(module); boundGetX(); // returns 81 Copy to Clipboard
Pollyfill for bind
The polyfill for bind is similar to call only difference is that it returns a function which is called with the
this
value and arguments providedFunction.prototype.myBind = function (obj = {}, ...args) { if (typeof this !== 'function') { throw new Error(this + ' cannot be bound as this is not callable'); } obj.fn = this; return () => { return obj.fn(...args); }; };
apply
The
apply()
method is similar to call()
method but calls the specified function with a given this
value, and arguments
provided as an array.For example, consider the following code:
const personDetails = { name: 'Jane', hello(age) { console.log("Hello " this.name + '! age:' + age); }, }; const newPersonDetails = { name: 'John', }; console.log(personDetails.hello.call(newPersonDetails, ["26"])); // Hello, John! age: 26
Lets take a look at a more examples
const array = ["a", "b"]; const elements = [0, 1, 2]; array.push.apply(array, elements); console.info(array); // ["a", "b", 0, 1, 2]
pollyfill for apply
The polyfill for bind is similar to
call()
only difference arguments provided are in arrayFunction.prototype.myApply = function (obj = {}, args = []) { if (typeof this !== 'function') { throw new Error(this + ' cannot be bound as this is not callable'); } obj.fn = this; obj.fn(...args); };
Hope this blog helped you understand the difference between
call()
bind()
and apply()
.