Это просто конвенция - но она продумана довольно хорошо, поэтому ее использовали по всему Угловому. См., Функция - модуль - может иметь только одну зависимость (как в вашем примере), или многие из них (начиная с двух, справа) или вообще не зависят. Поэтому нам нужно какое-то решение, которое отвечает на все случаи.
Наивный подход определяет все депо в качестве аргументов функции (ваш второй пример). Теперь можно извлечь (и ввести) их, проанализировав исходный код функции. Pro: абсолютный минимальный код для записи (в любом случае вам придется указывать все имена депо). Минусы: 1) на основе отражения (которое никогда не бывает быстрым), 2) ломается, когда скрипт минимизируется (и все имена параметров преобразуются).
Эти недостатки достаточно плохи, поэтому просто должен быть другой способ. Мы бы не захотели избавиться от списка аргументов, хотя (эти депилы все равно должны были быть рассмотрены внутри функции каким-то образом, верно?). Но теперь ясно, что единого списка недостаточно - его нужно где-то дублировать.
И вот здесь Array - упорядоченная последовательность элементов - пригодится. Теперь инжектору нужно отделить последний элемент этого массива, чтобы получить полный список депо. Это строки, а не переменные, поэтому они не будут модифицированы с помощью минификатора. Что еще лучше, теперь нам не нужно анализировать подпись, поэтому инжектор работает немного быстрее.
От теории к практике: это то, как эти два подхода реализуются в Angular 1.x DI модуле:
function annotate(fn, strictDi, name) {
var $inject,
fnText,
argDecl,
last;
if (typeof fn === 'function') {
// first approach: only function is passed, we need to analyze the args list
if (!($inject = fn.$inject)) {
$inject = [];
if (fn.length) {
if (strictDi) {
if (!isString(name) || !name) {
name = fn.name || anonFn(fn);
}
throw $injectorMinErr('strictdi',
'{0} is not using explicit annotation and cannot be invoked in strict mode', name);
}
// get rid of comments, it's possible to have those inside `()`
fnText = fn.toString().replace(STRIP_COMMENTS, '');
// extract arguments
argDecl = fnText.match(FN_ARGS);
// push those into injector
forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) {
arg.replace(FN_ARG, function(all, underscore, name) {
$inject.push(name);
});
});
// ... and that took some time
}
fn.$inject = $inject;
}
} else if (isArray(fn)) {
// second approach: an array is passed
last = fn.length - 1;
// make sure its last element is a function
assertArgFn(fn[last], 'fn');
// use all but the last element as list of deps
$inject = fn.slice(0, last);
// ... and that's all, believe it or not!
} else {
assertArgFn(fn, 'fn', true);
}
return $inject;
}
Как вы видите, первый if
ветвь для старинке - DEPS выражается как аргументы функции , Второй (гораздо легче читать и выполнять) - для отпечатков и функций, помещенных в массив (функция является последним элементом).
Это не упоминается в JS, потому что это просто соглашение, но легкое для подражания. В соответствующем коде достаточно проверить тип аргумента: если это просто функция, попытайтесь извлечь зависимость, проанализировав ее исходный код. – raina77ow
Нет, вы можете передать кучу строк до того, как функция и угловые обработают их. – kappaallday