Call, Bind And Apply in JavaScript with pollyfills.
Tags: javascript, webdev, programming
Published: 2022-10-28 09:36:41

## 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:


```jsx
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 this


```jsx

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

```


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.


```jsx
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 

```jsx
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:


```jsx
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


```jsx
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 provided


```jsx
Function.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:


```jsx
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


```jsx
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 array


```jsx
Function.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()`.