JavaScript – call() and apply()

Both methods  Object.call()  and Object.apply() allow to execute function in the specified execution scope passed as a parameter.

It has been  illustrated by following example:

Calling (in line 12)   father.celebrateBirthday()  method increments father.age to 51 and return that value. Even though object son doesn’t have that method implemented it can be called within its execution context, which is passed as first parameter to methods call()  and   apply() , as shown in lines: 15 and 18. Executing above code will output:

Difference between call() and  apply()

Methods behave exactly the same way but there is difference in how they have been called. Method  call()  requires arguments separated by comma (line 15). Method   apply()  requires second argument to be an array of arguments (line 18) that will be passed to executed function.

From practical point of view methods can be used interchangeable and often it comes down to a developer personal preference while dealing with short list of predefined arguments.

JsPerf – JavaScript performance toolkit was used  to compare efficiency of those methods. After checking few tests I decided to create own bit more complete test revision: “test call vs apply“. At the time of writing this article methods have been tested in IE, Firefox, Chrome and Safari. Check the test for more details.

It appears that while executing methods with no arguments  or passing just one argument call() method outperforms apply(). Results look much different for hundreds arguments passed into the function, where apply() was executed about 6 times faster – that would mean it should be used when it comes down to higher number of arguments passing to the function along with reference to defined execution scope.

Practical example

On developer.mozzilla.org pages explain quite well how and when to use both methods, so I will just highlight few examples in this post.

Build-in function ( apply())

There is number of functions that accept only arguments separated by comma, like: Math.min() or Math.max(). It is not a problem if we dealing with 2 or few more predefined numbers.But what about investigating numbers stored in the array? This is where Object.apply() magic comes handy. Instead of writing the code to loop through the array comparing pairs of numbers, it can be done with one line of code as shown below:

Another example would be pushing elements from one array into the other.   Array.push()  method accepts any number of arguments but what if those are stored in the array as shown below?

Yet again one line of code was used to push all elements from one array to the other, instead of the looping through all of them and pushing one at the time.

Another useful example for apply()  method is converting function arguments into instance of an Array.

Executing that code will produce false. To convert arguments into the array Object.apply() should be run from Array.prototype.slice() method (functions as first-class objects in JavaScript) could be used as shown below:

Self executing anonymous function ( call() )

Self executing anonymous function is commonly used by JavaScript developers. It is often executed with current scope passed as an argument which is assigned to internal parameter as in code blow.

There is however no need of creating new variable referencing execution context. Word this can be used easily instead if call()  method is used on evaluated function.

Please note that variable assignment is done just for the sake of the example and  this can be called directly inside function body.

Chaining constructors ( call())

Creating constructor chains in prototypal inheritance is important part of building JavaScript programs. Example below illustrates how objects can be created by constructor functions, with different arguments, build one on the top of another.

Let’s now create Programmer object to examine properties and prototypal chain.

Above code should generate output as below.

Person - first constructor function is  executed within context of Programmer constructor. That is why   this.{properties)} are created  inside of  Programmer instance instead of  Person instance. Last line  Programmer.prototype = Person.prototype fixes correct prototype chain to enable instanceof() check against  Person constructor.

Chaining constructors ( apply())

…coming soon

Note

Few days ago I wrote JavaScript Confusing Bits trying to cover everything I personally considered confusing during my recent JavaScript studies. Reading it again I realized that there are few more things that could be added there. Object.call()  and Object.apply()  are one of those missing “bits” but because of amount of content I decided to cover those separately.

References

Freelance developer, IT enthusiast, blogger with entrepreneurial spirit and passion for making games

Tagged with:
, , ,
Posted in
Technical

Leave a Reply

Categories