AngularJS コントローラーの 'this' と $scope の比較 質問する

AngularJS コントローラーの 'this' と $scope の比較 質問する

の中にAngularJS ホームページの「コンポーネントの作成」セクション次のような例があります。

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);
  }
}

selectメソッドが に追加されています$scopeが、addPaneメソッドが に追加されていることに注意してくださいthis。 これを に変更すると$scope.addPane、コードが壊れます。

ドキュメントには実際に違いがあると書かれていますが、その違いが何であるかは書かれていません。

this以前のバージョンの Angular (1.0 RC より前) では、 メソッドと を互換的に使用できました$scopeが、現在はそうではありません。 スコープで定義された メソッドと の内部ではthis、 は$scope互換可能です (Angularthisは に設定します$scope) が、コントローラー コンストラクター内ではそうではありません。

AngularJS コントローラーではthisと はどのように機能しますか?$scope

ベストアンサー1

「AngularJS コントローラーではthisと はどのように機能しますか?」$scope

短い答え

  • this
    • コントローラーのコンストラクター関数が呼び出されると、thisコントローラーになります。
    • オブジェクトで定義された関数が$scope呼び出されると、thisは「関数が呼び出されたときに有効だったスコープ」になります。これは、$scope関数が定義されている である可能性があります (またはそうでない可能性があります)。したがって、関数内では、thisと は同じではない$scope可能性があります。
  • $scope
    • すべてのコントローラーには関連付けられた$scopeオブジェクトがあります。
    • コントローラー (コンストラクター) 関数は、関連付けられているモデルのプロパティと関数/動作を設定する役割を担います$scope
    • この$scopeオブジェクト (およびプロトタイプ継承が使用されている場合は親スコープ オブジェクト) で定義されたメソッドのみが HTML/ビューからアクセスできます。例: ng-click、フィルターなど。

長い答え:

コントローラ関数はJavaScriptのコンストラクタ関数です。コンストラクタ関数が実行されると(例えば、ビューがロードされるとき)、this(つまり「関数コンテキスト」)がコントローラオブジェクトに設定されます。したがって、「tabs」コントローラコンストラクタ関数では、addPane関数が作成されると

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

これは $scope ではなく、コントローラ オブジェクト上に作成されます。ビューは addPane 関数を参照できません。ビューは $scope で定義された関数にのみアクセスできます。言い換えると、HTML ではこれは機能しません。

<a ng-click="addPane(newPane)">won't work</a>

「tabs」コントローラーのコンストラクター関数が実行されると、次のようになります。

タブコントローラコンストラクタ関数の後

破線の黒い線はプロトタイプ継承を示しています。分離スコープはプロトタイプ継承を行います。範囲(HTML 内でディレクティブが検出された場所の有効なスコープからプロトタイプ的に継承されるわけではありません。)

ここで、ペイン ディレクティブのリンク関数は、タブ ディレクティブと通信しようとします (つまり、何らかの方法でタブ分離 $scope に影響を与える必要があります)。イベントを使用することもできますが、別のメカニズムとして、ペイン ディレクティブをrequireタブ コントローラーにすることもできます (ペイン ディレクティブをタブ $scope に関連付けるメカニズムはないようですrequire)。

そこで、次のような疑問が生じます。タブ コントローラーにしかアクセスできない場合、タブ分離 $scope (これが本当に必要なことです) にはどのようにアクセスすればよいのでしょうか。

答えは赤い点線です。addPane() 関数の「スコープ」(ここでは JavaScript の関数スコープ/クロージャを参照しています) は、関数にタブ分離 $scope へのアクセスを提供します。つまり、addPane() が定義されたときに作成されたクロージャにより、addPane() は上の図の「タブ IsolateScope」にアクセスできます。(代わりに tabs $scope オブジェクトで addPane() を定義した場合、ペイン ディレクティブはこの関数にアクセスできず、したがって tabs $scope と通信する方法がありません。)

質問の残りの部分に答えるとhow does $scope work in controllers?:

$scope で定義された関数内では、this関数が呼び出された場所/時間に有効な $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(唯一)は

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

最初のリンクをクリックすると、thisと が$scope同じであることが示されます。これは、「関数が呼び出されたときに有効だったスコープ」が に関連付けられたスコープであるためですParentCtrl

this2 番目のリンクをクリックすると、 とは同じではない$scopeことがわかります。これは、「関数が呼び出されたときに有効だったスコープ」が に関連付けられたスコープであるためです。したがって、ここでは がの に設定されます。メソッド内では、は の $scope のままです。ChildCtrlthisChildCtrl$scope$scopeParentCtrl

フィドル

特に ng-repeat、ng-include、ng-switch、およびディレクティブはすべて独自の子スコープを作成できることを考慮すると、どの $scope が影響を受けるのかが混乱するため、$scope で定義されthisた関数内では使用しないようにしています。

おすすめ記事