Reputation: 19154
Starting to get into angular.js, I've seen a common pattern relating to arguments of callbacks. An example is the ui-router documentation:
var myApp = angular.module('myApp', ['ui.router']);
myApp.config(function($stateProvider, $urlRouterProvider) {
// Do stuff with ui-router providers
}):
But, from want I've seen, the myApp.config
callback's arguments could be different and it would still behave as expected:
myApp.config(function(OtherProvider) {
// Do stuff with provider from another service
});
How does myApp.config
know the difference? Is there done weird magic introspection going on, or is there some basic JS concept that allows for this? E.g. something like:
myApp.config = function(callback) {
var providerNames = callback.argumentNames;
var providers = this.findProviders(providerNames);
};
Perhaps I'm too used to python, where this sort of feature would only be possible through some very scary hacks.
Upvotes: 5
Views: 3696
Reputation: 61925
This is a "scary hack" used by Angular for one method of dependency injection - where the service names are automatically resolved from the argument names. There is no intrinsic support for such an operation at the language level.
The argument values (but not the argument names) can be accessed via the arguments
object within the function. However, the argument names themselves can only be accessed by applying [[ToString]]
to the function object and parsing the result1, which is a "scary hack".
In the explicit forms the injected parameters must appear in the same order as the list of supplied dependencies - in this case the names of the parameters don't matter because the service names have been supplied separately.
An excerpt of the forms, from the linked documentation, slightly modified:
// service names supplied separately
// - only Order of parameters matters
someModule.controller('MyController',
['$scope', 'greeter', function(I_am_a_scope, greeter) { ..
// service names supplied separately
// - only Order of parameters matters
var MyController = function($scope, GREETER) { ..
MyController.$inject = ['$scope', 'greeter'];
// "scary hack" magic of Angular JS, as service names not specified separately
// - the Name of the parameters is used as service name
// arguably Too Much Magic (TM), and a source of pain for minification
someModule.controller('MyController', function(greeter, $scope) { ..
The first two forms use Function.prototype.apply, which is similar to apply() in Python. The third asks for, and parses, the textual representation of the function - a "scary hack".
1To see how the magical form can be implemented, consider the following:
f = function (a,b) { return a+b }
f.toString() // e.g. -> "function (a, b) { return a + b; }"
ECMAScript 5 says Function.prototype.toString returns:
An implementation-dependent representation of the function is returned. This representation has the syntax of a FunctionDeclaration. Note in particular that the use and placement of white space, line terminators, and semicolons within the representation String is implementation-dependent.
(I'm not aware of any modern browsers that don't return a 'usable' result; the behavior of returning a representation is not optional is ES5.)
Upvotes: 2
Reputation: 1908
This is basically part of javascript. Javascript is very very flexible regarding functional arguments when it is invoking.
For example you declare a function:
function abc (first, second) {
}
But when you call it, you can pass any number of arguments even without zero argument. If you don't pass an argument but it has been defined when declaring the function, you will get value 'undefined' for that particular argument but it does not interrupt code execution.
Javascript provide a special local array (Basically everything is object in JS) named 'arguments' inside the function. I am calling special because it an Array with only one Array properties 'length' other Array methods or properties are unavailable
abc(firs,second,third)
Inside abc, we can check provided arguments
function abc (first, second) {
var args_total = arguments.length;
var no_of_defined_args = Function.length;
}
Yes Function.length is another properties by which you can check how many arguments are really defined by this function
Upvotes: 2