Function.prototype.call()
With the call() method, you can write a method that can be used on different objects. In other words with call(), an object can use a method belonging to another object. More information
const person = {
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
const person1 = {
firstName:"John",
lastName: "Doe"
}
const person2 = {
firstName:"Mary",
lastName: "Doe"
}
// This will return "John Doe":
console.log(person.fullName.call(person1));
The call() allows for a function/method belonging to one object to be assigned and called for a different object.
call() provides a new value of this to the function/method. With call(), you can write a method once and then inherit it in another object, without having to rewrite the method for the new object.
> Using call to chain constructors for an object
You can use call to chain constructors for an object (similar to Java).
In the following example, the constructor for the Product object is defined with two parameters: name and price.
Two other functions, Food and Toy, invoke Product, passing this, name, and price. Product initializes the properties name and price, both specialized functions define the category.
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);
console.log(cheese);
console.log(fun);
> Using call to invoke an anonymous function
In this example, we create an anonymous function and use call to invoke it on every object in an array.
The main purpose of the anonymous function here is to add a print function to every object, which is able to print the correct index of the object in the array.
const animals = [
{ species: 'Lion', name: 'King' },
{ species: 'Whale', name: 'Fail' }
];
for (let i = 0; i < animals.length; i++) {
(function(i) {
this.print = function() {
console.log('#' + i + ' ' + this.species
+ ': ' + this.name);
}
this.print();
}).call(animals[i], i);
}
> Using call to invoke a function and specifying the context for 'this'
In the example below, when we call greet, the value of this will be bound to object obj.
function greet() {
const reply = [this.animal, 'typically sleep between', this.sleepDuration].join(' ');
console.log(reply);
}
const obj = {
animal: 'cats', sleepDuration: '12 and 16 hours'
};
greet.call(obj); // cats typically sleep between 12 and 16 hours
> Using call to invoke a function and without specifying the first argument
In the example below, we invoke the display function without passing the first argument. If the first argument is not passed, the value of this is bound to the global object.
var sData = 'Wisen';
function display() {
console.log('sData value is %s ', this.sData);
}
display.call(); // sData value is Wisen
Note: In strict mode, the value of this will be undefined. See below.
'use strict';
var sData = 'Wisen';
function display() {
console.log('sData value is %s ', this.sData);
}
display.call(); // Cannot read the property of 'sData' of undefined
For more read you can visit reference
Function.prototype.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.
const module = {
x: 42,
getX: function() {
return this.x;
}
};
const unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// expected output: undefined
const boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// expected output: 42
> Creating a bound function
The simplest use of bind() is to make a function that, no matter how it is called, is called with a particular this value.
A common mistake for new JavaScript programmers is to extract a method from an object, then to later call that function and expect it to use the original object as its this (e.g., by using the method in callback-based code).
Without special care, however, the original object is usually lost. Creating a bound function from the function, using the original object, neatly solves this problem:
this.x = 9; // 'this' refers to global 'window' object here in a browser
const module = {
x: 81,
getX: function() { 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);
console.log(boundGetX());
// returns 81
> Partially applied functions
The next simplest use of bind() is to make a function with pre-specified initial arguments.
These arguments (if any) follow the provided this value and are then inserted at the start of the arguments passed to the target function, followed by whatever arguments are passed to the bound function at the time it is called.
function list() {
return Array.prototype.slice.call(arguments);
}
function addArguments(arg1, arg2) {
return arg1 + arg2;
}
const list1 = list(1, 2, 3);
// [1, 2, 3]
const result1 = addArguments(1, 2);
// 3
// Create a function with a preset leading argument
const leadingThirtysevenList = list.bind(null, 37);
// Create a function with a preset first argument.
const addThirtySeven = addArguments.bind(null, 37);
const list2 = leadingThirtysevenList();
// [37]
const list3 = leadingThirtysevenList(1, 2, 3);
// [37, 1, 2, 3]
const result2 = addThirtySeven(5);
// 37 + 5 = 42
const result3 = addThirtySeven(5, 10);
// 37 + 5 = 42
// (the second argument is ignored)
> With setTimeout()
By default within setTimeout(), the this keyword will be set to the window (or global) object. When working with class methods that require this to refer to class instances, you may explicitly bind this to the callback function, in order to maintain the instance.
function LateBloomer() {
this.petalCount = Math.floor(Math.random() * 12) + 1;
}
// Declare bloom after a delay of 1 second
LateBloomer.prototype.bloom = function() {
window.setTimeout(this.declare.bind(this), 1000);
};
LateBloomer.prototype.declare = function() {
console.log(`I am a beautiful flower with ${this.petalCount} petals!`);
};
const flower = new LateBloomer();
flower.bloom();
// after 1 second, calls 'flower.declare()'
And if you want to know more about bind method, read this resource