0

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 ?

sravan ganji
  • 2,930
  • 3
  • 14
  • 28

3 Answers3

2
  • we need (want) call and apply because they are much simpler than the alternative (depending on the use case, obviously)
  • we need call and apply because the alternative does not work on objects to which we cannot assign a property (frozen or sealed)
  • we need call and apply when the method is not supposed to be a property of the object during the evaluation of the function

Also 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()?.

Bergi
  • 513,640
  • 108
  • 821
  • 1,164
2

Indeed, defining the method on the object will be viable alternative in many cases. However, sometimes it is not an option:

1. The object does not allow the method to be defined:

"use strict";
function showDetails() { console.log(this.name); }
var obj = Object.seal({ name: 'Strawberry' });
showDetails.call(obj); // Strawberry
obj.showDetails = showDetails; // fails

2. Object already has a property with that name

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).

3. Adding the property influences the return value

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

4. Adding the property influences the remaining code

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.
    }
}

Other examples for 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

ES6 Considerations

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
trincot
  • 211,288
  • 25
  • 175
  • 211
0

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);
  }
}
Shishir Arora
  • 4,257
  • 2
  • 22
  • 30