How does implicit/inline/$inject dependency injection work in AngularJS?

后端 未结 2 912
暖寄归人
暖寄归人 2020-12-30 14:23

I\'m new to AngularJS and I would like to understand more about the dependencies that are being injected by default. While reading through code I\'ve noticed that sometimes

相关标签:
2条回答
  • 2020-12-30 14:28

    Just to provide a different sort of answer, as to the how inline/implicit dependencies work in AngularJS. Angular does a toString on the provided function and parses the parameter names from the string which is produced. Example:

    function foo(bar) {}
    foo.toString() === "function foo(bar) {}"
    

    References:

    source code

    AngularJS Dependency Injection - Demystified

    0 讨论(0)
  • 2020-12-30 14:41

    Yes, dependency injection in Angular works via the names of the components you (and Angular - for the internal ones) registered.

    Below is an example showing how a service is registered and injected into a controller using several different annotations. Please note that dependency injection always works the same in Angular, i.e. it doesn't matter if you are injecting something into a controller, a directive or a service.

    app.service('myService', function () {
        // registering a component - in this case a service
        // the name is 'myService' and is used to inject this
        // service into other components
    });
    

    Two use (inject) this component in other components, there are three different annotations I am aware of:

    1. Implicit Annotation

    You can either specify a constructor function which takes as parameters all the dependencies. And yes, the names need to be the same as when these components were registered:

    app.controller('MyController', function ($http, myService) {
        // ..
    });
    

    2. Inline Array Annotation

    Or you can use a notation using an array, where the last parameter is the constructor function with all the injectables (variable names do not matter in this case). The other values in the array need to be strings that match the names of the injectables. Angular can this way detect the order of the injectables and do so appropriately.

    app.controller('MyController', ['$http', 'myService', function ($h, m) {
        /* Now here you can use all properties of $http by name of $h & myService by m */
        // Example
        $h.x="Putting some value"; // $h will be $http for angular app
    }]);
    

    3. $inject Property Annotation

    A third option is to specify the $inject-property on the constructor function:

    function MyController($http, myService) {
        // ..
    }
    MyController.$inject = ['$http', 'myService'];
    app.controller('MyController', MyController);
    

    The reason why the last two options are available, at least as far as I know, is due to issues which occured when minifying the JavaScript files which led to the names of the parameters being renamed. Angular then wasn't able to detect what to inject anymore. In the second two cases the injectables are defined as strings, which are not touched during minification.

    I would recommend to use version 2 or 3, as version 1 won't work with minification/obfuscation. I prefer version 3 as from my point of view it is the most explicit.

    You can find some more detailed information in the internet, e.g. on the Angular Developer Guide.

    0 讨论(0)
提交回复
热议问题