angular this vs $scope (How does 'this' and $scope work in AngularJS controllers?)

"How does 'this' and $scope work in AngularJS controllers?"

Short answer:

  • 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/behavior 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.

Long answer:

A controller function is a JavaScript constructor function. When the constructor function executes (e.g., when a view loads), this (i.e., the "function context") is set to the controller object. So in the "tabs" controller constructor function, when the addPane function is created

this.addPane = function(pane) { ... }

it is created on the controller object, not on $scope. Views cannot see the addPane function -- they only have access to functions defined on $scope. In other words, in the HTML, this won't work: <a ng-click="addPane(newPane)">won't work</a>.

After the "tabs" controller constructor function executes, we have the following:

after tabs controller constructor function

The dashed black line indicates prototypal inheritance -- an isolate scope prototypically inherits fromScope. (It does not prototypically inherit from the scope in effect where the directive was encountered in the HTML.)

Now, the pane directive's link function wants to communicate with the tabs directive (which really means it needs to affect the tabs isolate $scope in some way). Events could be used, but another mechanism is to have the pane directive require the tabs controller. (There appears to be no mechanism for the pane directive to require the tabs $scope.)

So, this begs the question: if we only have access to the tabs controller, how do we get access to the tabs isolate $scope (which is what we really want)?

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.)

To answer the other part of your question: how does $scope work in controllers?:

Within functions defined on $scope, this is set to "the $scope in effect where/when the function was called". Suppose we have the following 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>

And the ParentCtrl (Solely) has

$scope.logThisAndScope = function() {
    console.log(this, $scope)}

Clicking the first link will show that this and $scope are the same, since "the scope in effect when the function was called" is the scope associated with the ParentCtrl.

Clicking the second link will reveal this and $scope are not the same, since "the scope in effect when the function was called" is the scope associated with the ChildCtrl. So here, this is set to ChildCtrl's $scope. Inside the method, $scope is still the ParentCtrl's $scope.

Fiddle

I try to not use  this inside of a function defined on $scope, as it becomes confusing which $scope is being affected, especially considering that ng-repeat, ng-include, ng-switch, and directives can all create their own child scopes.

html : 

<!doctype html>
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js"></script>
<script src="components.js"></script>
<script src="app.js"></script>
<link rel="stylesheet" href="bootstrap.css">
</head>
<body>
<tabs>
<pane title="Localization">
Date: {{ '2012-04-01' | date:'fullDate' }} <br>
Currency: {{ 123456 | currency }} <br>
Number: {{ 98765.4321 | number }} <br>
</pane>
<pane title="Pluralization">
<div ng-controller="BeerCounter">
<div ng-repeat="beerCount in beers">
<ng-pluralize count="beerCount" when="beerForms"></ng-pluralize>
</div>
</div>
</pane>
</tabs>
</body>
</html>


js: 
angular . module ( 'components' ,  [])
 
. directive ( 'tabs' ,  function ()  {
return  {
restrict :  'E' ,
transclude :  true ,
scope :  {},
controller :  function ( $scope ,  $element )  {
var  panes  =  $scope . panes  =  [];
 
$scope . select  =  function ( pane )  {
angular . forEach ( panes ,  function ( pane )  {
pane . selected  =  false ;
});
pane . selected  =  true ;
}
 
this . addPane  =  function ( pane )  {
if  ( panes . length  ==  0 )  $scope . select ( pane );
panes . push ( pane );
}
},
template :
'<div class="tabbable">'  +
'<ul class="nav nav-tabs">'  +
'<li ng-repeat="pane in panes" ng-class="{active:pane.selected}">' +
'<a href="" ng-click="select(pane)">{{pane.title}}</a>'  +
'</li>'  +
'</ul>'  +
'<div class="tab-content" ng-transclude></div>'  +
'</div>' ,
replace :  true
};
})
 
. directive ( 'pane' ,  function ()  {
return  {
require :  '^tabs' ,
restrict :  'E' ,
transclude :  true ,
scope :  {  title :  '@'  },
link :  function ( scope ,  element ,  attrs ,  tabsController )  {
tabsController . addPane ( scope );
},
template :
'<div class="tab-pane" ng-class="{active: selected}" ng-transclude>'  +
'</div>' ,
replace :  true
};
})








test
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值