AngularJS - How does the DI system know of the name of the arguments?

强颜欢笑 提交于 2019-12-20 10:06:54

问题


Example straight from the official site:

function PhoneListCtrl ($scope, $http) {
    $http.get('phones/phones.json').success(function(data) {
        $scope.phones = data;
    });

    $scope.orderProp = 'age';
}

The $scope and $http arguments are unique identifiers for locating corresponding AngularJS services inside the DI system. So how does the DI system retrieve the variable name of these arguments, exactly?


回答1:


This is the trimmed down version of the way

var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var FN_ARG_SPLIT = /,/;
var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;

function annotate(fn){
    var $inject
    if (!($inject = fn.$inject)) {
        $inject = [];
        fnText = fn.toString().replace(STRIP_COMMENTS, '');
        argDecl = fnText.match(FN_ARGS);
        angular.forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
            arg.replace(FN_ARG, function(all, underscore, name){
                $inject.push(name);
            });
        });
        fn.$inject = $inject;
    }

    return fn.$inject;
}

Demo: Fiddle(See the console);

Steps:
1. Calling toString in the function returns the function source
2. Remove all comments using regex
3. Extract the arguments from the source using regex




回答2:


Straight from the source @GitHub:

The simplest form is to extract the dependencies from the arguments of the function. This is done by converting the function into a string using toString() method and extracting the argument names.

// Given
function MyController($scope, $route) {
    // ...
}
// Then
expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);

And the annotate function

function annotate(fn) {
  var $inject,
  fnText,
  argDecl,
  last;

  if (typeof fn == 'function') {
    if (!($inject = fn.$inject)) {
      $inject = [];
      fnText = fn.toString().replace(STRIP_COMMENTS, '');
      argDecl = fnText.match(FN_ARGS);
      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
        arg.replace(FN_ARG, function(all, underscore, name){
        $inject.push(name);
      });
    });
    fn.$inject = $inject;
    }
  } else if (isArray(fn)) {
    last = fn.length - 1;
    assertArgFn(fn[last], 'fn')
    $inject = fn.slice(0, last);
  } else {
    assertArgFn(fn, 'fn', true);
  }
  return $inject;
}

as seen on row 45 and later



来源:https://stackoverflow.com/questions/15270311/angularjs-how-does-the-di-system-know-of-the-name-of-the-arguments

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