1. Call & Apply
Using the call and apply methods we can invoke the function with the new context. The values will be attached to that execution only.
The difference between call and apply is that apply accepts arguments in an array, while call accepts it normally.
function showName(title) {
console.log(title + " " + this.name);
}
function Example(name) {
this.name = name;
}
const Example1 = new Example("John");
const Example2 = new Example("Anna");
showName.call(Example1, "Mr.");
showName.apply(Example2, ["Mrs."]);
// Output
Mr. John;
Mrs. Anna;
2. Bind - Permanent Binding
Permanent binding When using bind, we can create a new function with the new values and store it in a variable, and then use it further. It creates fresh permanent binding without affecting the original function.
function showName(title) {
console.log(title + " " + this.name);
}
function Example(name) {
this.name = name;
}
const Example1 = new Example("John");
const Example2 = new Example("Anna");
const showExample1 = showName.bind(Example1);
const showExample2 = showName.bind(Example2);
showExample1("Mr.");
showExample2("Mrs.");
// Output
Mr.John;
Mrs.Anna;
3. What is the output?
const person = { name: "Arjunan" };
function sayAge(age) {
console.log(this.name + " is " + age + " years old.");
}
sayAge.call(person, 10); // Arjunan is 10 years old.
sayAge.bind(person, 10); //
sayAge.bind(person, 10)(); // Arjunan is 10 years old.
4. What is the output?
const person1 = {
name: "Arjunan",
age: 12,
getAge: function () {
console.log(this.age);
},
};
const person2 = { age: 50 };
person1.getAge.call(person2); // 50
person1.getAge.apply(person2) // 50
person1.getAge.bind(person2)() // 50
5. What is the output?
var status = "Happy";
setTimeout(() => {
const status = "Fruit";
const data = {
status: "Sad",
getStatus() {
console.log(this.status);
},
};
data.getStatus(); // Sad
data.getStatus.call(this); // Happy
}, 0);
// data.getStatus() have context of data when it is initialized and called.
// this in call have access to window and var Happy is defined in window.
// this will look for parent of the setTimeout callback which is window.
6. What is the output?
const animals = [
{ species: "Lion", name: "King" },
{ species: "Tiger", name: "Queen" },
];
function printAnimals(i) {
this.print = function () {
console.log(i + " " + this.species + ": " + this.name);
};
this.print();
}
for (let i = 0; i < animals.length; i++) {
printAnimals.call(animals[i], i);
}
// 0 Lion: King
// 1 Tiger: Queen
7. Append Array to an Array
let a = [1, 2, 3]
let b = ["a", "b", "c"]
// Create new array
console.log([...a, ...b]) // [ 1, 2, 3, 'a', 'b', 'c' ]
console.log(a.concat(b)) // [ 1, 2, 3, 'a', 'b', 'c' ]
a.push(...b)
a.push.call(a, ...b)
a.push.apply(a, b)
console.log(a) // [ 1, 2, 3, 'a', 'b', 'c' ]
8. Bound Function
function f() {
console.log(this);
}
let user = {
g: f.bind(null),
};
user.g(); // window
// the context of f() is set to window since bind is evoked with null
9. Bind Chaining
Once bind is set to a object, it will not change. There is nothing like bind chaining.
function f() {
console.log(this.name);
}
let fn = f.bind({ name: "Arjun" }).bind({ name: "Ann" });
fn(); // Arjun
10. Fix Password Issue
success and failed function donot have access to this.name so inorder to fix this we need to provide functions by binding the user object to get access to this.name.
function checkPassword(success, failed) {
let password = prompt("Password: ");
if (password === "arjun") success();
else failed();
}
let user = {
name: "Appu",
loginSuccess() {
console.log(this.name + " logged in");
},
loginFailed() {
console.log(this.name + " login failed");
},
};
checkPassword(user.loginSuccess, user.loginFailed);
// arjun - undefined logged in
// xyz - undefined login failed
checkPassword(user.loginSuccess.bind(user), user.loginFailed.bind(user));
// arjun - Appu logged in
// xyz - Appu login failed
11. Partial Application of Login
function checkPassword(success, failed) {
let password = prompt("Password: ");
if (password === "arjun") success();
else failed();
}
let user = {
name: "Appu",
login(result) {
console.log(this.name + (result ? " logged in" : " login failed"));
},
};
checkPassword(user.login.bind(user, true), user.login.bind(user, false));
// arjun - Appu logged in
// xyz - Appu login failed
12. Bind in Arrow Function
call, apply, bind donot make any difference in arrow function. It will work in the way arrow function is defined.
const age = 10;
let person1 = {
name: "Arjun",
age: 20,
getAgeArrow: () => console.log(this.age),
getAge: function () {
console.log(this.age);
},
};
let person2 = {
age: 100,
};
person1.getAge(); // 20
person1.getAgeArrow(); // undefined
person1.getAge.bind(person2)(); // 100
person1.getAgeArrow.bind(person2)(); // undefined