回答編集履歴

1 a

pinpikokun

pinpikokun score 361

2016/11/28 17:37  投稿

## javascriptのthis
javascriptのthisはどこが呼び出しているかよりも、どいつが呼び出しているか
によって値が左右されるため、呼び出し方によっては期待した動作をしないことがあります。
※単純にコントローラー(どこが)に作成したメソッドが呼ばれるわけではありません
以下のサンプルですとwindowオブジェクトがthisになっています。
ですので単純にthisを使おうとすると呼び出し側の事を考えなければなら無い為
「var self = this;」等としてthisの値を別の変数に置き換えるとわかりやすいと思います。
## 補足
call,apply,bind,アロー関数等を使うとその限りではありません
## 動作サンプル
[リンク](http://plnkr.co/edit/u165pNAMywLKb6zc5Z9o?p=preview)
## コード
```html
<html>
<head>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.3/angular.min.js"></script> 
 <script>
 
   // グローバルな呼び出し
   window.a = function(){
     alert('windowオブジェクトのa()が呼び出されました')
   }
 
   // angularjsの定義
   var app = angular.module('myApp', []);
   
   // コントローラー
   app.controller('LoginController', function($scope, LoginService) {
     
     var self = this;
     
     $scope.login = function(){
       LoginService.login().then(function(){
         
         if(this.a){
           this.a();
         }else{
           alert('this.a()が呼び出されませんでした');
         }
         
         if(self.a){
           self.a();
         }else{
           alert('this.a()が呼び出されませんでした');
           alert('self.a()が呼び出されませんでした');
         }
         
         if($scope.a){
           $scope.a();
         }else{
           alert('$scope.a()が呼び出されませんでした');
         }
       });
     }
     
     // thisの呼び出し
     this.a = function(){
       alert('LoginController(this)のa()が呼び出されました');
     }
     
     // selfの呼び出し
     self.a = function(){
       alert('LoginController(self)のa()が呼び出されました');
     }
     
     // $scopeの呼び出し
     $scope.a = function(){
       alert('LoginController($scope)のa()が呼び出されました');
     }
     
   });
   
   // サービス
   app.factory('LoginService', function($q, $timeout){
     var self = {};
     
     // 非同期ログイン処理
     self.login = function(){
       var d = $q.defer();
       $timeout(function() {
         alert('ログイン完了!');
         d.resolve();
       }, 1000);
       return d.promise;
     }
     
     // サービスのthis呼び出し
     this.a = function(){
       alert('LoginService(this)のa()が呼び出されました');
     }
     
     // サービスのself呼び出し
     self.a = function(){
       alert('LoginService(self)のa()が呼び出されました');
     }
     
     return self;
   });
 </script>
 </head>
 <body>
   <div ng-app="myApp">
     <div ng-controller="LoginController">
       <button ng-click="login()">ログイン</button>
     </div>
   </div>
 </body>
</html>
```

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る