理解 AngularJS 函数 $arguments

aqu*_*tae 5 javascript parameters angularjs

开始接触 angular.js,我看到了与回调参数相关的常见模式。ui-router 文档就是一个例子:

var myApp = angular.module('myApp', ['ui.router']);

myApp.config(function($stateProvider, $urlRouterProvider) {
    // Do stuff with ui-router providers
}):
Run Code Online (Sandbox Code Playgroud)

但是,从我所看到的来看,myApp.config回调的参数可能不同,但它仍然会按预期运行:

myApp.config(function(OtherProvider) {
    // Do stuff with provider from another service
});
Run Code Online (Sandbox Code Playgroud)

怎么myApp.config知道区别呢?是否正在进行奇怪的魔术内省,或者是否有一些基本的 JS 概念允许这样做?例如:

myApp.config = function(callback) {
    var providerNames = callback.argumentNames;
    var providers = this.findProviders(providerNames);
};
Run Code Online (Sandbox Code Playgroud)

也许我太习惯Python了,这种功能只有通过一些非常可怕的黑客才能实现。

use*_*740 2

Angular 用于一种依赖注入方法的“可怕的黑客” ——其中服务名称自动从参数名称解​​析。在语言级别上没有对此类操作的内在支持。

参数值(但不是arguments参数名称)可以通过函数内的对象访问。然而,参数名称本身只能[[ToString]]通过应用于函数对象并解析结果1来访问,这一个“可怕的黑客”。

在显式形式中,注入的参数必须以与提供的依赖项列表相同的顺序出现 - 在这种情况下,参数的名称并不重要,因为服务名称是单独提供的。

链接文档中的表格摘录,稍作修改:

// 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) { ..
Run Code Online (Sandbox Code Playgroud)

前两种形式使用Function.prototype.apply,它类似于Python 中的 apply()。第三个请求并解析函数的文本表示 - 一个“可怕的黑客”。


1要了解如何实现神奇形式,请考虑以下事项:

f = function (a,b) { return a+b }
f.toString() // e.g. -> "function (a, b) { return a + b; }"
Run Code Online (Sandbox Code Playgroud)

ECMAScript 5 表示Function.prototype.toString返回:

返回函数的依赖于实现的表示。该表示具有 FunctionDeclaration 的语法。请特别注意,表示字符串中空格、行终止符和分号的使用和放置取决于实现。

(我不知道有哪个现代浏览器不返回“可用”结果;ES5 中返回表示的行为不是可选的。)