epeleg
epeleg

Reputation: 10915

using .call vs. passing "this" in JavaScript

I know that if you have some javascript function and you want to call it such that using this within it would refer not to the object on which it was directly called you can use func.call(thatObject,param,and,more,params...).

But suppose you are the writer of func and the only usage for func is via func.call,
Why would you not define it to begin with as:

function func(that,param,and,more,params...) {
   //and in here use *that* and not *this*
}

yep, it looks less "cool" because its not a method of an object, but hey if the only usage for func is via func.call it all seems like just extra code and overhead.

Am I missing something here? or is the source code in which I have seen this pattern just "over OOed" ?

Upvotes: 1

Views: 373

Answers (3)

RustyToms
RustyToms

Reputation: 7810

There appears to be a large performance difference. Using

func(){
  //code here, this.something
}
func.call(thatObject)

according to the first couple of tests is about 8 times slower than using

func(that){
  //code here, that.something
}
func(thatObject)

Test it yourself, JSPerf here

Ultimately though, speed alone is rarely the most important factor in which code we use. Code is designed for people as much as it is for computers, we need to communicate our intentions clearly to both. Whichever makes the code cleanest is best, and we should follow conventions whenever it is feasible. I personally prefer the second option here, but I think the general convention is the first. So I think you use call in most situations, except for when you need the fastest code possible or if the convention changes.

Upvotes: 2

ZenMaster
ZenMaster

Reputation: 12742

func.call is intended to be used when an alternative (or any) context for the function is needed to be provided.

Your suggestion is odd, since, when you define the function using this pattern:**

function func(that,param,and,more,params...) {
   //and in here use *that* and not *this*
}

it's either:

doesn't belong to any object

in which case passing an object to act as this doesn't make any sense, since there should be no this.someThing calls to begin with

or belongs to a different object or is defined to be a plug to an object

in which case it does exactly what func.call would do, while contaminating the definition of the function with redundant parameter.

UPDATE:

Think of the second example in this way - imagine that some set of Objects (what you'd call from the same "class") allow injection of arbitraty functions, say for iteration over all properties of the object and some summary or manipulation or what have you.

In Java, the common pattern is to create an Iterator and pass it, and its main purpose is to serve as sort of placeholder so that next and hasNext methods can be called - since Java doesn't really have object-less functions. (granted there is some additional logic there, but let's leave it alone for the sake of this discussion).

JavaScript does not neeed this! All these call and apply methods do not need to have some additional Iterator object to hold them. They can be defined "detached" from any object, while still with intention to be used in a context of one (hence this usage in their code) and injected into code that knows to accept such functions.

The "host" code than only needs to call or apply them, knowing that this will refer to itself - this very "host" object.

This leads to a more concise, reusable and portable code, IMO.

UPDATE 2:

See more here.

Upvotes: 0

Tanmoy
Tanmoy

Reputation: 45652

Your pattern will work in this scenario but in general it has some problems ...

  1. Constructor functions -> We create objects by using new keyword where 'this' object is automatically created and returned (default) also has the link with the function's prototype.

  2. When calling the function someone might forget to pass 'that' object and your code will fail. In case of call if you pass null it is reset to global object (non-strict mode which is common)

Upvotes: 0

Related Questions