【问题标题】:How does angular's controller method make $scope available to my function argumentangular 的控制器方法如何使 $scope 可用于我的函数参数
【发布时间】:2016-02-18 20:56:06
【问题描述】:

我正在寻找一个伪代码答案,或概念性答案。


经过多年的编程,我从未创建过一个接收函数参数的类方法,以便方法的调用者自动访问“不可见”属性。

如果我尝试在 my_app.controller(...) 方法之外访问 $scope,我会收到一个错误,所以我知道它不是全局的;如果我尝试从my_app.$scopeangular.$scope 访问它,我会得到未定义。

那么我的函数参数如何访问它:

    my_app.controller('my_controller' , function( $scope , ... ) { ... }

更新(据我所知):

  // javascript
  var my_class =   function( argument_A )                 
                       { this.some_prop = argument_A ;        

                         this.some_method = function( argument_B ) 
                           { console.log( argument_B ) ; // function(boo)
                           } ;
                       } ;

  var my_instance = new my_class( "my_string" ) ;

  var my_function_argument = function( boo ){ } ;
  my_instance.some_method( my_function_argument ) ; 

【问题讨论】:

  • 当控制器通过 ng-controller 指令附加到 DOM 时,Angular 将使用指定控制器的构造函数实例化一个新的控制器对象。将创建一个新的子作用域,并作为 $scope 的控制器构造函数的可注入参数提供。 docs.angularjs.org/guide/controller
  • 我认为这是我的问题:如何创建一个“可注入参数”......也许我需要谷歌搜索它......但我想充分理解这个概念,这样我应该可以用任何其他语言做到这一点
  • 这就是所谓的“依赖注入”,第一次体验时确实觉得很“神奇”。

标签: javascript angularjs oop


【解决方案1】:

函数是一等公民

在 JavaScript 和其他现代语言(Scala、Haskell、LISP 等)中,函数被视为一等公民。具体来说,这意味着该语言支持将函数作为参数传递给其他函数,将它们作为来自其他函数的值返回,并将它们分配给变量或将它们存储在数据结构中。一些编程语言理论家也需要支持匿名函数(函数文字)。在具有一等函数的语言中,函数的名称没有任何特殊地位;它们被视为具有函数类型的普通变量。1

上面的例子可以重构为:

var myController = function ($scope, ... ) {
     console.log($scope);
     $scope.message = "Hello world"
};

my_app.controller('my_controller' , myController );

在这种情况下,.controller 方法将 myController 对象存储在 AngularJS $controllerProvider 服务的缓存中。 IE。 cache["my_controller"] = myController;

稍后当$compile 服务遇到需要控制器的指令时:

<div ng-controller="my_controller">
    {{message}}
</div>

$compile 服务创建一个新作用域,从$controller 服务缓存中检索myController 函数,并以新作用域作为函数的第一个参数调用该函数。

$compile 服务还创建了一个 $watch 监听函数来跟踪 $scope.message 变量。在每个摘要周期中,如果 $scope.message 发生更改,则 DOM 会相应更新。

在问题的例子中:

//These are function invocations, the variable must be defined

console.log( boo )              ; //    ERROR: boo is not defined
my_instance.some_method( boo )  ; //    ERROR: boo is not defined

最后一种形式使用匿名函数字面量(或函数表达式)。匿名函数是作为参数传递给名为.some_method 的方法的对象。

//The anonymous function is an object passed as an argument
//boo is a parameter to be supplied when the function is invoked

my_instance.some_method( function( boo ) { } ) ; // NO ERROR

有关函数字面量的更多信息,请参阅MDN JavaScript Reference -- function expression


依赖注入和按名称连接参数

通常在 JavaScript 中,函数参数是按位置连接的。在 AngularJS 框架中,函数参数是按名称注入的。这是怎么做到的?

来自文档:

推理

在 JavaScript 中,对函数调用 toString() 会返回函数定义。然后可以解析定义并提取函数参数。

-- AngularJS $injector Service API Reference -- Inference

所以在例子中:

my_app.controller('my_controller' , function( $scope , ... ) { ... }

$injector 服务在控制器构造函数上执行toString() 并对其进行解析。服务检测到$scope 是函数的第一个参数,并使用该知识正确调用函数。

您可以看到fn.toString() 正在使用here in the source code

【讨论】:

  • 这似乎是答案的一部分(也许是第二部分)......但似乎第一部分是理解如何突然出现一个变量... ...例如,$scope 是从哪里来的?为什么它没有产生错误......它不是全局的,它没有在最本地容器的范围内定义......但显然 js(以及显然其他语言)允许(故意?......它是语言的错误?...是否会由此产生任何类型的出血效应?)这种类型的语法...
  • $scope 在这种情况下是合法的,因为在它被调用之前,它只是函数定义的一部分;猜猜是什么调用了这个函数? AngularJS ......它将函数定义解析为 AngularJS 系统中的已知实体(包括$scope、Angular 服务和提供者,以及用户定义的服务)。这不是错误,因为调用代码知道要为$scope 变量“注入”什么。
  • 查看我对作为一等公民的职能的解释。
  • 你的 FAFCC 部分的第一个代码 sn-p 真的很清楚......由于某种原因我没有看到......但现在我明白为什么 boo 没有触发错误...感谢您花时间澄清...
  • 也许我可以建议您将 FAFCC 作为答案的第一部分,因为它表明了为什么以前未声明的 $scope 是公平的(因为它甚至不是变量......它是一个匿名函数)... .... 并将 toString 解释作为您答案的第二部分,因为它解释了类方法(例如.controller(...))在收到匿名函数后会发生什么...
【解决方案2】:

当您创建一个函数并在函数参数中传递 dependency 名称时,在这种情况下,Angular 通过从其 DI 容器中解析该依赖项来为每个依赖项创建一个对象。这种依赖注入技术称为constructor function(还有两种DI技术)。

当您使用 ng-controller 指令在 DOM 上注入控制器时,函数将传递给 $controllerProviderregister 函数。控制器功能称为工厂功能。它将以依赖项作为参数传递。 $injector 服务从函数中获取每个依赖项,并执行 $injector.get 以返回在 DI 容器中注册的依赖项。在返回 $scope 依赖项时,它使用 $rootScope.$new(isolate, parent) 方法从 rootScope 创建新的 scope$new 方法采用两个参数,第一个作为bool,第二个作为parentScope 参数。其他从注册组件直接取出到模块的依赖。

【讨论】:

  • 我觉得这解释了它一旦发生是如何处理的,但我对它的实际发生方式感到困惑......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多