3

Take a simple anonymous function which accepts 3 parameters:

function hello(firstname, surname, city) {
    console.log('Hi ' + firstname + ' ' +
                        surname + '. I see you\'re from ' + city)
}

What is the benefit of calling this function using the function method "call" over say just calling the function?, ie.

hello('Jane','Mansfield','Philadelphia');

vs

hello.call(this,'Jane','Mansfield','Philadelphia');

Fiddle-dee-dee: http://jsfiddle.net/wC3xz/1/

Sorry, but looking at the docs hasn't shed any light. The only thing I can think of is if you can gain access to the this object passed to the function. But wouldn't accessing this from within the anonymous function be this in the context of the anonymous function ie the window?

When is call needed instead of just functionname(args)?

Yatrix
  • 12,038
  • 13
  • 39
  • 73
dewd
  • 4,300
  • 2
  • 25
  • 42
  • 2
    `call` is only necessary if your function uses `this`. In the particular case of your `hello` function, you'll never see any difference because it doesn't use `this`. – apsillers May 23 '13 at 15:22
  • https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/call Did you see this? – Yatrix May 23 '13 at 15:23
  • @aspillers but how do you access this within the destination function? surely it will be this in the context of the destination function not where you're calling from. – dewd May 23 '13 at 15:25
  • 1
    @dewd The value of `this` within a function changes [depending on how the function is called](http://stackoverflow.com/questions/12370851/understanding-javascript-scope-with-var-that-this/12371105#12371105). `call` allows you **circumvent the normal rules** and freely specify a `this` value. – apsillers May 23 '13 at 15:25
  • @aspillers. Your link is the answer. Thx man. – dewd May 23 '13 at 15:28

4 Answers4

10

So what's the big deal about call?

Call is defined in the spec in section 15.3.4.4. You use .call when you are trying to set the thisArg inside the function.

How would Ito use it?

Here is an example of how you would use it:

var me = { name: 'dr.eval' }

foo.call(me); // if you omitted the 'call' it would error because this defaults to the window object.

function foo() {
    alert(this.name + ' is home');
}

you can read more about it here: Function.prototype.call

When would I use it?

Here is a very canonical example when using call:

A lot of DOM methods return NodeList. While NodeList is an array-like object, you cannot natively call array methods on them. However, since they are, by design, like arrays, you can use array methods on them using .call

If you open the console and type

document.getElementsByTagName("a").forEach

You'd get undefined, because it returns a NodeList, which does not have a forEach method. However, iterating a NodeList might be desirable, so you can do the following:

[].forEach.call(document.getElementsByTagName("a"),function(elem){
     console.log(elem);
});

Which would log all the anchor elements on the page.

Another common example is arguments which is another "Array Like" object. Often, we want to process arguments like an array but we can't. So again, .call comes to the rescue and we can do:

[].slice.call(arguments,0); // returns a clone of arguments, but a real array we can work with!

It's also useful when working with events, and in general it shows how flexible JavaScript is. It's a way to share functionality between objects that otherwise would not have been able to share it.

canon
  • 37,149
  • 9
  • 67
  • 92
dr.eval
  • 116
  • 1
  • 5
  • 3
    Nice, I added a more common example. – Benjamin Gruenbaum May 23 '13 at 15:29
  • @dr.eval Thanks so much. This clarifies it nicely. – dewd May 23 '13 at 15:36
  • 1
    @BenjaminGruenbaum Thx for playing policeman on this one. You really helped reiterate the point I was trying to make. – dewd May 23 '13 at 15:37
  • @dewd You're welcome. That's the only way we can keep SO a high quality Q&A site. If people do not answer your question don't be afraid to tell them that. Your question was solid and if dr.eval hadn't answered it I would have done so myself. I'm satisfied with this answer atm. – Benjamin Gruenbaum May 23 '13 at 15:38
  • @BenjaminGruenbaum yep me too. I can take the examples and clearly see the difference. – dewd May 23 '13 at 15:41
  • I want you all to know that I die a little inside every time you instantiate an array just to hijack its methods. – canon May 23 '13 at 15:55
  • @canon I don't care :) You're welcome to change it to Array.prototype if you'd like. – Benjamin Gruenbaum May 23 '13 at 16:12
  • @BenjaminGruenbaum I've just discovered that your example can be done without call. Try: Array.slice(arguments). Not sure how supported it is, but it's in ECMAScript 5. – dewd May 24 '13 at 11:40
  • @dr.eval Same goes with foreach. Array.forEach(document.getElementsByTagName("a"),function(elem){ console.log(elem);}) works. No call required. – dewd May 24 '13 at 11:46
  • @dr.eval in the foo example, what's wrong with console.log(arguments[0].name)? No need for call there. – dewd May 24 '13 at 11:55
2

What is the benefit of calling this function using the function method "call" over say just calling the function?

  • None. It is useful only if you want to transfer context (this) to the function

When is call needed instead of just functionname(args)?

  • when you want to call existing method in different context than it is defined. For example, arguments object is similar to Array, but you can not use sort() directly.

    function Test() {
      // call sort from Array context onto arguments object
      console.log(Array.prototype.sort.call(arguments)); // 2 3 5 8
      // error: arguments object doesn't contain sort
      console.log(arguments.sort());
    }
    Test(5,3,8,2);
    
Jan Turoň
  • 26,696
  • 21
  • 102
  • 153
  • @dewd This is an another good example of when to use `call` , again, we have an array like object (arguments) and we're calling `.sort` on it, which we would otherwise not have been able to. – Benjamin Gruenbaum May 23 '13 at 15:48
  • @BenjaminGruenbaum yeah, I saw it and have given it a +1 – dewd May 23 '13 at 15:54
1

You use

.call

and

.apply

when it comes to overriding.

this is a good article to learn more.

rlemon
  • 16,698
  • 11
  • 85
  • 121
Jonast92
  • 4,861
  • 1
  • 14
  • 30
0

The benefit of using call() in general is that it allows you to set the context for the function explicitly. There's not much value in that for a simple function as you show, but if your function is a method of an object or if it's a callback, setting the context can be relevant.

Stephen Thomas
  • 12,855
  • 2
  • 27
  • 46
  • _HOW_ can it be relevant? Methods and callbacks are two _good_ examples, can you explain _why_ setting this might be useful in such a scenerio? – Benjamin Gruenbaum May 23 '13 at 15:26