4

I was looking at injector code of angular and could not understand this line

Function.prototype.bind.apply(ctor, args)

of code. Why would we call apply for bind? isn't it like calling apply for apply?

I read it on some question that it can be used to call a function of arbitrary arguments, but that can be done with arguments object, right?

Can some one clear this?

Actual angular code:

 function instantiate(Type, locals, serviceName) {
      // Check if Type is annotated and use just the given function at n-1 as parameter
      // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
      var ctor = (isArray(Type) ? Type[Type.length - 1] : Type);
      var args = injectionArgs(Type, locals, serviceName);
      // Empty object at position 0 is ignored for invocation with `new`, but required.
      args.unshift(null);
      return new (Function.prototype.bind.apply(ctor, args))();
    }

1 Answers1

5

Skip the Function.prototype.bind.apply

First we will see apply.

The apply() method calls a function with a given this value and arguments provided as an array (or an array-like object).

Syntax

fun.apply(thisArg, [argsArray])

So with the above syntax it is clearly understood that apply method calls the given function with first argument as this and second argument as Array

So lets breakdown into steps

  • Function.prototype.bind will return a new function with pre-bound this value. ( and it is introduced in ES5 ).
  • apply method invokes a function with given two parameters as below.
    1. First parameter is this
    2. Second parameter is Array / Array like object
  • So in our case we are passing ctor as this and args as Array / Array like object to apply method.

Here comes the final version return new (Function.prototype.bind.apply(ctor, args))();

  • We can break down the above line into two lines so that it will be easily readable.
    1. var func = Function.prototype.bind.apply(ctor, args);
    2. 'return new func();`

And the above code is used by injector to get the instance of service in angular.

By definition an Angular service will return the new'ed function so the above code is doing the same.

Services return the object through a function constructor. That is why you can use the keyword ‘this’ inside the Service.

function instantiate(Type, locals, serviceName) {
      // Check if Type is annotated and use just the given function at n-1 as parameter
      // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
      var ctor = (isArray(Type) ? Type[Type.length - 1] : Type);
      var args = injectionArgs(Type, locals, serviceName);
      // Empty object at position 0 is ignored for invocation with `new`, but required.
      args.unshift(null);
      return new (Function.prototype.bind.apply(ctor, args))();
    }
Gangadhar Jannu
  • 4,136
  • 6
  • 29
  • 49