How do the function argument names in Angular.js objects connect to other objects?

Problem

Let's say I have made a module with a service and a controller in Angular.js, I am able to access that service inside of the controller like so:

var myapp = angular.module('my-app', []);

myapp.factory('Service', function() {
  var Service = {};
  Service.example = 'hello';
  //etc..
  return Service;
});

myapp.controller('mainController', function($scope, Service) {
  $scope.greeting= Service.example;
});

In this example, the Service object will be passed to the controller, and structuring the code like so will not change the behavior of the code:

myapp.controller('mainController', function(Service, $scope) {
  $scope.greeting= Service.example;
});

so, how does Angular.js "know" what the function arguments mean?

Problem courtesy of: GSto

Solution

Angular simply parses the toString() representation of the function for the names of dependencies. From the docs:

In JavaScript calling toString() on a function returns the function definition. The definition can then be parsed and the function arguments can be extracted.

However, note that this approach will fail if your code is minified. For that reason, Angular supports an alternative (I would suggest always using it) syntax, using an array:

myapp.controller('mainController', ["$scope", "Service", function($scope, Service) {
  $scope.greeting= Service.example;
}]);
Solution courtesy of: James Allardice

Discussion

This is accomplished by the quite clever method annotate (source) which takes a regex scan on function signature source (using function.toString()) and iteratively pushes each function argument into the function $inject array.

The same result is accomplished when manually specifying the $inject array as in:

var MyController = function($scope, myService) {
  // ...
}
// Define function dependencies
MyController.$inject = ['$scope', 'myCustomService'];
Discussion courtesy of: Stewie

This recipe can be found in it's original form on Stack Over Flow.