AngularJS - Как система DI знает название аргументов?
Пример прямо с официального сайта:
function PhoneListCtrl ($scope, $http) {
$http.get('phones/phones.json').success(function(data) {
$scope.phones = data;
});
$scope.orderProp = 'age';
}
Аргументы $scope
и $http
являются уникальными идентификаторами для нахождения соответствующих услуг AngularJS внутри системы DI. Итак, как система DI извлекает имя переменных этих аргументов точно?
Ответы
Ответ 1
Это сокращенная версия способа
var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var FN_ARG_SPLIT = /,/;
var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
function annotate(fn){
var $inject
if (!($inject = fn.$inject)) {
$inject = [];
fnText = fn.toString().replace(STRIP_COMMENTS, '');
argDecl = fnText.match(FN_ARGS);
angular.forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
arg.replace(FN_ARG, function(all, underscore, name){
$inject.push(name);
});
});
fn.$inject = $inject;
}
return fn.$inject;
}
Демо: Fiddle (см. консоль);
Шаги:
1. Вызов toString
в функции возвращает источник функции
2. Удалить все комментарии с помощью регулярного выражения
3. Извлеките аргументы из источника с помощью regex
Ответ 2
Прямо из источника @GitHub:
Простейшей формой является извлечение зависимостей из аргументов функция. Это делается путем преобразования функции в строку используя метод toString()
и извлечение имен аргументов.
// Given
function MyController($scope, $route) {
// ...
}
// Then
expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
И аннотированная функция
function annotate(fn) {
var $inject,
fnText,
argDecl,
last;
if (typeof fn == 'function') {
if (!($inject = fn.$inject)) {
$inject = [];
fnText = fn.toString().replace(STRIP_COMMENTS, '');
argDecl = fnText.match(FN_ARGS);
forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
arg.replace(FN_ARG, function(all, underscore, name){
$inject.push(name);
});
});
fn.$inject = $inject;
}
} else if (isArray(fn)) {
last = fn.length - 1;
assertArgFn(fn[last], 'fn')
$inject = fn.slice(0, last);
} else {
assertArgFn(fn, 'fn', true);
}
return $inject;
}
как показано на строке 45 и выше