JavaScript call(), apply(), and bind()
Every JavaScript function has three methods inherited from Function.prototype: call(), apply(), and bind(). These methods allow you to explicitly set the value of 'this' when calling a function, enabling method borrowing and partial application.
Function.call()
The call() method invokes a function with a specified 'this' value and arguments provided individually. It immediately executes the function.
const person = {
fullName: function(city, country) {
return this.firstName + ' ' + this.lastName + ', ' + city + ', ' + country;
}
};
const person1 = { firstName: 'Alice', lastName: 'Smith' };
const person2 = { firstName: 'Bob', lastName: 'Jones' };
// call(thisArg, arg1, arg2, ...)
console.log(person.fullName.call(person1, 'NYC', 'USA'));
console.log(person.fullName.call(person2, 'London', 'UK'));Function.apply()
The apply() method is similar to call(), but takes arguments as an array (or array-like object) instead of individually. It also immediately executes the function.
const person = {
fullName: function(city, country) {
return this.firstName + ' ' + this.lastName + ', ' + city + ', ' + country;
}
};
const person1 = { firstName: 'Alice', lastName: 'Smith' };
// apply(thisArg, [argsArray])
console.log(person.fullName.apply(person1, ['NYC', 'USA']));
// Useful with Math methods
const numbers = [5, 6, 2, 3, 7];
const max = Math.max.apply(null, numbers);
const min = Math.min.apply(null, numbers);
console.log('Max: ' + max);
console.log('Min: ' + min);
// Modern alternative with spread:
console.log('Max (spread): ' + Math.max(...numbers));Function.bind()
The bind() method creates a new function with a fixed 'this' value. Unlike call() and apply(), bind() does NOT immediately execute the function. It returns a new function that can be called later.
const user = {
name: 'Alice',
greet: function() {
return 'Hello, I am ' + this.name;
}
};
// Without bind: 'this' is lost
const greetFunc = user.greet;
// greetFunc() would have 'this' as undefined in strict mode
// With bind: 'this' is permanently set
const boundGreet = user.greet.bind(user);
console.log(boundGreet());
// bind with different object
const admin = { name: 'Bob (Admin)' };
const adminGreet = user.greet.bind(admin);
console.log(adminGreet());Setting 'this' Explicitly
All three methods let you control what 'this' refers to inside a function. This is crucial when methods are passed as callbacks or used in different contexts.
| Method | Executes immediately? | Arguments | Returns |
|---|---|---|---|
| call() | Yes | Individual args | Function result |
| apply() | Yes | Array of args | Function result |
| bind() | No | Individual args (partial) | New function |
function introduce(greeting, punctuation) {
return greeting + ', I am ' + this.name + punctuation;
}
const person = { name: 'Alice' };
// call - immediate, individual args
console.log(introduce.call(person, 'Hi', '!'));
// apply - immediate, array of args
console.log(introduce.apply(person, ['Hey', '!!']));
// bind - returns new function
const boundIntro = introduce.bind(person, 'Hello');
console.log(boundIntro('...'));
console.log(boundIntro('!!!'));Borrowing Methods
You can borrow methods from one object and use them on another. This is especially useful for array-like objects that don't have array methods.
// Borrowing array methods for array-like objects
function listArguments() {
// 'arguments' is array-like but not an array
const args = Array.prototype.slice.call(arguments);
console.log('Args: ' + args.join(', '));
}
listArguments('a', 'b', 'c');
// Borrowing methods between objects
const calculator = {
value: 0,
add: function(n) { this.value += n; return this; },
getValue: function() { return this.value; }
};
const myObj = { value: 10 };
calculator.add.call(myObj, 5);
console.log('Borrowed result: ' + calculator.getValue.call(myObj));Partial Application with bind()
bind() can pre-fill some arguments of a function, creating a new function with fewer parameters. This is called partial application.
function multiply(a, b) {
return a * b;
}
// Create specialized functions using partial application
const double = multiply.bind(null, 2);
const triple = multiply.bind(null, 3);
const times10 = multiply.bind(null, 10);
console.log('double(5): ' + double(5));
console.log('triple(5): ' + triple(5));
console.log('times10(5): ' + times10(5));
// Practical example: logging with prefix
function log(level, message) {
console.log('[' + level + '] ' + message);
}
const info = log.bind(null, 'INFO');
const error = log.bind(null, 'ERROR');
info('Server started');
error('Connection lost');