Difference in controller declaration in AngularJS

ぐ巨炮叔叔 提交于 2020-02-15 09:38:20

问题


I have seen controller being declared in two ways as below. But what diff does this make?

  1. appmodule.controller('Actrl',['$scope',function($scope) {}]);
  2. appmodule.controller('Actrl',function($scope) {});

But, most of the times, the 1st doesn't work. Why?


回答1:


Both the syntax are same but the first one is preferred (there is a typo, see below description) if you are minifying your code.

Angular resolves the dependency based on the name so when you write appmodule.controller('Actrl',function($scope) {}); syntax, Angular injects the dependency of $scope by reading the argument name $scope. But when your code is minified for production level use then your code will become like:

appmodule.controller('Actrl', function(a) {});

Now, the Angular will not be able to resolve the dependency with the name a. That is why the first approach is used i.e. appmodule.controller('Actrl',['$scope', function($scope) {}]);. Now when your code is minimized for production, your code will be like this:

 appmodule.controller('Actrl',['$scope', function(a) {}]);

Now, Angular can match the index based position that a is $scope.

There is a typo in your code where the list should not be closed before the function declaration.

Read the Dependency Annotation for more information on this under the topic Inline Array Annotation.

Angular invokes certain functions (like service factories and controllers) via the injector. You need to annotate these functions so that the injector knows what services to inject into the function. There are three ways of annotating your code with service name information:

  • Using the inline array annotation (preferred)
  • Using the $inject property annotation
  • Implicitly from the function parameter names (has caveats)

Edit: Another more detailed description over the two different style: a-note-on-minification:

Since Angular infers the controller's dependencies from the names of arguments to the controller's constructor function, if you were to minify the JavaScript code for PhoneListCtrl controller, all of its function arguments would be minified as well, and the dependency injector would not be able to identify services correctly.

We can overcome this problem by annotating the function with the names of the dependencies, provided as strings, which will not get minified. There are two ways to provide these injection annotations:




回答2:


[EDIT] For your first case, this isn't the right syntax. The right one would be to encapsulate in the same array your dependency injection and your controller like the following:

appmodule.controller('Actrl',['$scope', function($scope) {}]);

The difference between both of your definitions is that in the first case you're explicitly specifying your injection dependencies. This will avoid to rename variables name during minification which would break your code. Hence the name in quotes [i.e. those strings] will be used in the minified versions.

Both approach are doing the same thing but the second one is just a syntactic sugar of the first one.




回答3:


These are just two ways that AngularJS does Dependancy Injection. But this version,

appmodule.controller('Actrl',['$scope',function($scope) {}]);

in particular has been written to handle code minification. It is recommended use this version whenever possible.

To get the difference clear, you must first understand how AngualarJS does dependancy injection. For more details you can refer to:

  1. Understanding Dependency Injection
  2. The "Magic" behind AngularJS Dependency Injection
  3. AngularJS Dependency Injection - Demystified

But to cut the long story short, AngularJS loops through each items by their names in the parameter list, looks up against a list of known names of objects that can be injected and then injects the objects if there is a match.

Let's have a look at an example:

appmodule.controller('myController',function($scope, $log) {
    $log.info($scope);
});

Here, since $scope and $log (the order that you specify them in the parameter list doesn't matter here) are known objects to AngularJS, it injects them into myController. But if you were to do:

appmodule.controller('myController',function(someVar) {
     // ...
});

AngularJS doesn't know about the parameter someVar and it throws a dependancy error.

Now let's come back to your example. Let me modify your 2nd version a bit:

appmodule.controller('Actrl',function($scope, $log) {
    $log.info($scope);
});

If we use a minifier, let's see how this piece of code gets minified. I am using an online minifier for this purpose . After minification, it becomes:

appmodule.controller("Actrl",function(o,l){l.info(o)});

This is because, minifiers usually shorten the variable names to smallest size to save space. Notice how our $scope got renamed to o and $log to l.

Now, if we run this code, AngularJS doesn't know about o and l and it is going to cry about missing dependencies as we understood earlier.

AngularJS deals with this problem using the 1st version of Dependency Injection in your example. If it was:

appmodule.controller('Actrl',['$scope','$log', function($scope, $log) {
    $log.info($scope);
}]);

After minification it becomes:

appmodule.controller('Actrl',['$scope','$log',function(o,l){l.info(o)}]);

Here, even though $scope and $log parameters were renamed to o and l respectively, the minifier didn't touch the strings '$scope' and '$log' and their order in the array.

Now when AngularJS injector sees this version using array, it substitutes each item in the parameter list in the function with the corresponding objects in the array (provided the objects are known to AngularJS).

So in our example, even after minification, AngularJS knows that it needs to substitute o with $scope and l with $log. Thus the code runs without any Dependancy Injection errors.

But one important thing is to note here is that, when we use this version the order of the items specified in the array and the parameter list of the function of really matters. That is, if you were to do:

appmodule.controller('Actrl',['$scope','$log', function($log, $scope) {
    $log.info($scope);
}]);

, it is going to blow everything up!



来源:https://stackoverflow.com/questions/35336180/difference-in-controller-declaration-in-angularjs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!