Reputation: 5125
i have seen these examples for call,apply and bind
var fruit = { name: 'Strawberry' }
function showDetails(size, price) {
console.log(this.name + ' ' + size + ': $' + price + '/lb')
}
showDetails.apply(fruit, ['small', 10])
// Strawberry small: $10/lb
showDetails.call(fruit, 'small', 10)
// Strawberry small: $10/lb
var bound = showDetails.bind(fruit, 'small', 10)
bound()
//Strawberry small: $10/lb
showDetails.bind(fruit, 'small', 10)()
// Strawberry small: $10/lb
here all functions do the same thing and check the below code with out using any of these(call,apply and bind)
var fruit = { name: 'Strawberry' };
function showDetails(size, price) {
console.log(this.name + ' ' + size + ': $' + price + '/lb')
}
fruit.show =showDetails;
fruit.show(small,10); //Strawberry small: $10/lb
it worked same as expected so why ,when do we need call,apply and bind.
how to use these functions in ES6 ?
Upvotes: 0
Views: 109
Reputation: 350290
Indeed, defining the method on the object will be viable alternative in many cases. However, sometimes it is not an option:
"use strict";
function showDetails() { console.log(this.name); }
var obj = Object.seal({ name: 'Strawberry' });
showDetails.call(obj); // Strawberry
obj.showDetails = showDetails; // fails
function name() { console.log(this.name) }
var obj = Object.seal({ name: 'Strawberry' });
name.call(obj); // Strawberry
obj.name = name;
obj.name(); // does not show 'Strawberry', but the function
It could also fail if the said property is read-only (with defineProperty
and writable: false
).
Suppose the function performs self inspection, e.g. it counts the number of properties it has:
function memberCount() { return Object.keys(this).length; };
var obj = { name: 'Strawberry' };
console.log(memberCount.call(obj)); // 1
obj.count = memberCount;
console.log(obj.count()); // 2
This is especially a problem with objects of which you expect a certain behaviour, like arrays:
function first() { return this[0]; };
var arr = ['Strawberry', 'Banana'];
console.log(first.call(arr)); // Strawberry
arr.first = first;
// ...
for (var i in arr) { // Iterate through array
if (arr.hasOwnProperty(i)) {
console.log(arr[i]); // Oops, the function appears also.
}
}
apply
and bind
There are other examples where the use of apply
or bind
is useful in case the target object already has the method:
apply
may be used with methods that require separate arguments, while you just have an array of values. In ES6 you can use the spread syntax to overcome this, but traditionally, apply
was the solution for this.
For example, to get the minimum value in an array:
var arr = [5,3,1,6,2];
console.log(Math.min.apply(Math, arr));
The bind
method is often used to pass a method as a callback, but you need it to be bound to your object:
var obj = {
flavour: 'Strawberry',
smell: function () { console.log(this.flavour) }
};
window.addEventListener('load', obj.smell); // ......> undefined
window.addEventListener('load', obj.smell.bind(obj)); // .....>Strawberry
Where this
must be bound, there can still be use for these methods. But with the arrow function syntax, this
keeps its lexical value, and passing the this
argument to apply
, call
or bind
on such function has no effect. Often it also becomes unnecessary, as that lexical this
is often exactly what is needed.
Take the example of getting the minimum value of an array. With ES6 it can be written as follows:
const arr = [5,3,1,6,2,4];
console.log(Math.min(...arr));
Or take an example where a method (using this
) is passed as callback:
class Cls {
constructor() {
this.flavour = 'Strawberry'
this.smell = () => console.log(this.flavour)
}
};
window.addEventListener('load', (new Cls).smell); // ......> Strawberry
Upvotes: 3
Reputation: 5923
we can achieve same thing by appending the function to object in javascript
You are right as per your example. But in javascript we need to pass functions as callbacks to browser-event-loop-queue to execute async. In such cases the object will be lost. Check below example
var fruit = { name: 'Strawberry' };
function showDetails(size, price) {
console.log(this.name + ' ' + size + ': $' + price + '/lb')
}
fruit.show =showDetails;
setTimeout(fruit.show, 100);
Here output will be undefined, so to attach the arguments and context object, we need "bind"
and now we can make above work with
setTimeout(fruit.show.bind(fruit, size, price), 100);
Use for apply/call is to execute a function, by dynamically supplying its context and arguments. Check follwoing usage of call.
var Array.protoype.forEach = function(cb /*, thisArg*/){
var T;
if (arguments.length > 1) {
T = arguments[1];
}
for(var i =0; i<this.length; i++){
cb.call(T, this[i], i, this);
}
}
Upvotes: 0
Reputation: 664548
call
and apply
because they are much simpler than the alternative (depending on the use case, obviously)call
and apply
because the alternative does not work on objects to which we cannot assign a property (frozen or sealed)call
and apply
when the method is not supposed to be a property of the object during the evaluation of the functionAlso we need apply
because call
cannot work with a dynamic number of arguments (ignoring new spread syntax), see What is the difference between call and apply?. And bind
is a completely different beast, see Javascript call() & apply() vs bind()?.
Upvotes: 2