“this和$scope在AngularJS控制器中是如何工作的?”
简短的回答:
this
When the controller constructor function is called, this is the controller.
When a function defined on a $scope object is called, this is the "scope in effect when the function was called". This may (or may not!) be the $scope that the function is defined on. So, inside the function, this and $scope may not be the same.
$scope
Every controller has an associated $scope object.
A controller (constructor) function is responsible for setting model properties and functions/behaviour on its associated $scope.
Only methods defined on this $scope object (and parent scope objects, if prototypical inheritance is in play) are accessible from the HTML/view. E.g., from ng-click, filters, etc.
长一点的回答:
控制器函数是JavaScript的构造函数。当构造函数执行时(例如,当视图加载时),this(即“函数上下文”)被设置为控制器对象。在"tabs"控制器构造函数中,当addPane函数被创建时
this.addPane = function(pane) { ... }
它创建在控制器对象上,而不是在$scope上。视图不能看到addPane函数——它们只能访问在$scope上定义的函数。换句话说,在HTML中,这是行不通的:
<a ng-click="addPane(newPane)">won't work</a>
在"tabs"控制器构造函数执行后,我们得到如下结果:
虚线表示原型继承——一个孤立的范围原型继承自scope。(它并不从HTML中遇到指令的作用域继承。)
现在,pane指令的link函数想要与tabs指令通信(这实际上意味着它需要以某种方式影响tabs隔离$scope)。可以使用事件,但另一种机制是让窗格指令需要选项卡控制器。(似乎没有机制让窗格指令要求选项卡$scope。)
所以,这就引出了一个问题:如果我们只能访问选项卡控制器,我们如何访问选项卡隔离的$scope(这是我们真正想要的)?
Well, the red dotted line is the answer. The addPane() function's "scope" (I'm referring to JavaScript's function scope/closures here) gives the function access to the tabs isolate $scope. I.e., addPane() has access to the "tabs IsolateScope" in the diagram above because of a closure that was created when addPane() was defined. (If we instead defined addPane() on the tabs $scope object, the pane directive would not have access to this function, and hence it would have no way to communicate with the tabs $scope.)
回答你问题的另一部分:$scope如何在控制器中工作?:
在$scope上定义的函数中,这将被设置为“在函数被调用的位置/时间生效的$scope”。假设我们有以下HTML:
<div ng-controller="ParentCtrl">
<a ng-click="logThisAndScope()">log "this" and $scope</a> - parent scope
<div ng-controller="ChildCtrl">
<a ng-click="logThisAndScope()">log "this" and $scope</a> - child scope
</div>
</div>
而ParentCtrl (only)具有
$scope.logThisAndScope = function() {
console.log(this, $scope)
}
单击第一个链接将显示this和$scope是相同的,因为“函数被调用时生效的作用域”是与ParentCtrl关联的作用域。
点击第二个链接将显示this和$scope是不一样的,因为“函数被调用时生效的作用域”是与ChildCtrl关联的作用域。这里,这个被设置为ChildCtrl的$scope。在方法内部,$scope仍然是ParentCtrl的$scope。
小提琴
我尽量不在$scope上定义的函数中使用这个,因为这会让人感到困惑,尤其是考虑到ng-repeat、ng-include、ng-switch和指令都可以创建自己的子作用域。