简体   繁体   English

JavaScript匿名函数参数名称重要吗?

[英]Are JavaScript anonymous function parameter names significant?

I'm going through this Angular tutorial and have noticed that variables seem to be freely added to functions as needed. 我正在阅读此Angular教程 ,并注意到变量似乎可以根据需要自由添加到函数中。 I figured up to this point that there were just conventions but am I mistaken? 到目前为止,我已经确定只有约定,但是我误会了吗? Consider the last file: 考虑最后一个文件:

app.controller('PostsCtrl', function ($scope, $location, Post) {
    $scope.posts = Post.all;

    $scope.post = {url: 'http://'};

    $scope.submitPost = function () {
      Post.create($scope.post).then(function (ref) {
        $location.path('/posts/' + ref.name());
      });
    };

Here "$location" was added to function() between $scope and Post. 在这里,“ $ location”被添加到$ scope和Post之间的function()中。 Is $location the only option for the 2-nd parameter in an anonymous function here with 3 parameters or is angular somehow looking at the name of the 2nd parameter and deducing that it needs to inject $location there? $ location是这里带有3个参数的匿名函数中第二个参数的唯一选项吗?还是角度地看了第二个参数的名称并推断出它需要在其中注入$ location? Where in the documentation can I see all the conventions for 1, 2, 3, etc parameter versions of this function? 在文档的哪里可以看到该函数的1、2、3等参数版本的所有约定?

This code doesn't appear to work btw. 这段代码似乎无法正常工作。 Post is undefined. 帖子未定义。

With angular, the names are significant; 用角表示,名称有意义的。 in plain javascript, not really. 用普通的javascript,不是真的。

With that, however, if you wanted them to be insignificant in the example above, you could do: 但是,如果您希望它们在上面的示例中无关紧要,则可以执行以下操作:

app.controller('PostsCtrl', ['$scope','$location', 'Post', 
    function (foo, bar, foobar) {
        ....
    }
]);

In which case you're mapping the first, second, and third parameters to $scope , $location , and Post respectively. 在这种情况下,您要将第一个,第二个和第三个参数分别映射到$scope$locationPost This is actually a better way to do this, as when you minify with angular, it is going to change the names of those parameters, and it is going to break it. 这实际上是一个更好的方式来做到这一点,当你的角度, 要改变这些参数的名称作为再压缩,并且要打破它。

In this case, you could order those parameters however you'd like. 在这种情况下,您可以根据需要订购这些参数。 Angular uses Dependency Injection to supply dependencies to your controller. Angular使用依赖注入为控制器提供依赖关系。 In this case, it will infer those dependencies based on the names so you can order them however you'd like. 在这种情况下,它将根据名称推断出这些依赖关系,因此您可以根据需要对其进行排序。

Unfortunately, using this method with minification is impossible. 不幸的是,将这种方法最小化是不可能的。 In that case, you need to specify your dependencies. 在这种情况下,您需要指定依赖项。 Your controller function must then take them in the order that they are defined: 然后,控制器函数必须按照定义的顺序使用它们:

app.controller('PostsCtrl', 
    ['$scope','$location','Post', function($scope, $location, Post) {
}]);

Ahh I was confused by this at first as well. 最初我也为此感到困惑。 Angular has a nice feature called Dependency Injection . Angular有一个很好的功能,称为依赖注入 The names do matter because angular looks at the names of the parameters and decides what object to pass to the function. 名称很重要,因为angular会查看参数的名称并确定要传递给函数的对象。 In this rare case in JavaScript, names matter but order does not. 在JavaScript这种罕见的情况下,名称很重要,但顺序无关紧要。

The answer here is really Angular specific. 答案实际上是特定于Angular的。 You want to read about Dependency Injection here: 您想在这里阅读有关依赖注入的信息:

https://docs.angularjs.org/guide/di https://docs.angularjs.org/guide/di

The Implicit Dependencies section should be good reading. 隐式依赖项一节应该很好阅读。 In short, the name does matter for Angular but the order does not. 简而言之,名称对于Angular确实很重要,但顺序无关紧要。 This is NOT the case for raw JavaScript however. 但是,原始JavaScript并非如此。

From the Angular site: 从Angular网站:

There are three equivalent ways of annotating your code with service name information: 可以使用三种等效的方法用服务名称信息来注释代码:

Implicitly from the function parameter names 从函数参数名隐式

Using the $inject property annotation 使用$ inject属性注释

Using the inline array annotation 使用内联数组注释

Since you already have other answers with Angular specific instructions, I'll try to explain in simple code how Angular achieves dependency injection in JavaScript and how one might go about doing something similar in plain JS. 由于您已经获得了有关Angular特定指令的其他答案,因此,我将尝试用简单的代码解释Angular如何在JavaScript中实现依赖注入以及如何在普通JS中执行类似的操作。

First it turns the function into a string, then reads the parameters, and extracts the property from the dependency container, and finally calls the function with the parameters that were extracted. 首先,它将函数转换为字符串,然后读取参数,并从依赖关系容器中提取属性,最后使用提取的参数调用函数。 Here's a very simple example of how one might do this: 这是一个如何执行此操作的非常简单的示例:

// parses function and extracts params
function di(app, f) {
  var args = f.toString()
    .match(/function\s+\w+\s*?\((.*?)\)/)[1] // weak regex...
    .split(/\s*,\s*/)
    .map(function(x){return app[x.replace(/^\$/,'')]})
  return function() {
    return f.apply(this, args)
  }
}

// Example

// A dependency container
var app = {
  foo: 'this is foo',
  baz: 'this is baz'
}

// this is like adding a function with the Angular ecosystem
// the order of arguments doesn't matter
var test = di(app, function test($foo, $baz) {
  console.log($foo) //=> this is foo
  console.log($baz) //=> this is baz
})

// No need to pass arguments, they were injected
test()
//$ this is foo
//$ this is baz

But handling DI by stringifying the function has drawbacks; 但是通过对函数进行字符串化处理DI有缺点。 old browsers don't support Function.prototype.toString very well, and minifiers will shorten the variable names making this technique useless. 旧的浏览器不能很好地支持Function.prototype.toString ,并且缩小器会缩短变量名,从而使该技术无用。 But Angular can get around this problem by injecting strings and parameters that match those strings; 但是Angular可以通过注入字符串与这些字符串匹配的参数来解决这个问题。 minifiers won't touch the strings. 缩小者不会碰串。

Obviously AngularJS does much more than this, but hopefully it will clear your mind on "how the hell is this possible?!" 显然AngularJS的作用远不止于此,但希望它能使您对“这到底怎么可能? -- Well, it's kind of a hack. -好吧,这是一种骇客。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM