2015-02-11 5 views
1

Пожалуйста, проверьте код, указанный ниже. Я только что проиллюстрировал ионный пример всплывающего окна.Использование 'this' внутри услуг AngularJS

На showAlert1() я ссылаюсь на это «как есть», и он не работает. В showAlert2() я использую вспомогательную переменную «_this», которая получает «это», и она работает.

Я видел подобные вещи, происходящие в других случаях, и я считаю, что это связано с синтаксисом «Контроллер как», но почему это происходит?

angular.module('myApp', ['ionic']) 
.controller('PopupCtrl',function($scope, $ionicPopup) { 

    this.testAlert = function() { 
    alert('Alerting!'); 
    }; 

    this.showAlert1 = function() { 
    $ionicPopup.alert({ 
     title: 'Don\'t eat that!', 
     template: 'It might taste good' 
    }, this).then(function() { 
     this.testAlert(); 
    }); 
    }; 

    this.showAlert2 = function() { 
    var _this = this; 
    $ionicPopup.alert({ 
     title: 'Don\'t eat that!', 
     template: 'It might taste good' 
    }, _this).then(function() { 
     _this.testAlert(); 
    }); 
    }; 

}); 

Вот код Pen: http://codepen.io/anon/pen/dPJVNN

Спасибо!

+0

Возможный дубликат [Как работает ключевое слово this?] (Http://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work) – JLRishe

ответ

2

«это» в javascript - это не то же самое, что «это» на других языках. Вы можете думать об этом скорее как о контексте вызова функции.

Контекст вызова по умолчанию в веб-приложении - это окно. Однако при вызове функции, являющейся свойством объекта, контекст становится объектом.

Таким образом, в вашем примере:

angular.module('myApp', ['ionic']) 
.controller('PopupCtrl',function($scope, $ionicPopup) { 
    //"this" refers to the controller instance here (controllers are created by angular with the "new" operator) 
    this.testAlert = function() { 
    //inside of this function, "this" will still be the controller 
    alert('Alerting!'); 
    }; 

    //"this" is the controller 
    this.showAlert1 = function() { 
    //"this" is still the controller 
    $ionicPopup.alert({ 
     title: 'Don\'t eat that!', 
     template: 'It might taste good' 
    }, this).then(function() { 
     //"this" is no longer the controller. It's probably "window", but it's possible that ionic sets this to some other parameter when it invokes the function. 
     //since it's not the controller, testAlert() is undefined! 
     this.testAlert(); 
    }); 
    }; 

    //"this" is the controller 
    this.showAlert2 = function() { 
    //"this" is still the controller, and you have assigned _this to also be the controller 
    var _this = this; 
    $ionicPopup.alert({ 
     title: 'Don\'t eat that!', 
     template: 'It might taste good' 
    }, _this).then(function() { 
     //"_this" is captured by the closure created by the function call, and it is still the controller, so testAlert() is defined. 
     _this.testAlert(); 
    }); 
    }; 

}); 

Вы часто будете видеть это в коде:

var self = this; 

С «я» который используется вместо этого, чтобы избежать путаницы, которая вы столкнулись.

angular.module('myApp', ['ionic']) 
.controller('PopupCtrl',function($scope, $ionicPopup) { 
    var self = this; 
    self.testAlert = function() { 
    alert('Alerting!'); 
    }; 

    self.showAlert1 = function() { 
    $ionicPopup.alert({ 
     title: 'Don\'t eat that!', 
     template: 'It might taste good' 
    }, self).then(function() { 
     self.testAlert(); 
    }); 
    }; 

    self.showAlert2 = function() { 

    $ionicPopup.alert({ 
     title: 'Don\'t eat that!', 
     template: 'It might taste good' 
    }, self).then(function() { 
     self.testAlert(); 
    }); 
    }; 

}); 
+0

Отличное объяснение. Благодаря! Есть ли способ узнать контекст всего объекта, что-то вроде дерева контекста? – Som

0

Ключевое слово «this» относится к текущему объекту, в котором он находится. Таким образом, в вашей функции showAlert1() это «относится» к объекту $ ionicPopup.

Так, например

var parent = { 
    value: 'parent', 
    alert: function(){ 
     alert(this.value); 
    }, 
    child: { 
     alert: function(){ 
      alert(this.value); 
     } 
    } 
} 

если вы делаете parent.alert(), он будет оповещать родителей. Но если вы выполните parent.child.alert(), он даст вам неопределенное значение, потому что «this.value» для дочернего объекта не существует, он не ссылается на parent.value. Так что это означает, что это относится к текущему объекту.

0

"это" в .then() обратного вызова в showAlert1 ссылается на глобальный объект. Попробуйте это:

angular.module('mySuperApp', ['ionic']) 
.controller('PopupCtrl',function($scope, $ionicPopup) { 

    this.testAlert = function() { 
    alert('Alerting!'); 
    }; 

    this.showAlert1 = function() { 
    $ionicPopup.alert({ 
     title: 'Don\'t eat that!', 
     template: 'It might taste good' 
    }, this).then(function() { 
     alert(this === window); 
     this.testAlert(); 
    }); 
    }; 

    this.showAlert2 = function() { 
    var _this = this; 
    $ionicPopup.alert({ 
     title: 'Don\'t eat that!', 
     template: 'It might taste good' 
    }, _this).then(function() { 
     _this.testAlert(); 
    }); 
    }; 

}); 

«это» работает только для showAlert1 и showAlert2, потому что вы имеете в виду их как свойство самого контроллера прямо здесь:

<button class="button button-primary" ng-click="popup.testAlert()"> 

Что предпочтительнее использует $ Объем:

<html ng-app="mySuperApp"> 
    <head> 
    <meta charset="utf-8"> 
    <title> 
     Popups 
    </title> 

    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no"> 

    <link href="//code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet"> 
    <script src="//code.ionicframework.com/nightly/js/ionic.bundle.js"></script> 

    </head> 
    <body class="padding" ng-controller="PopupCtrl"> 
    <button class="button button-primary" ng-click="testAlert()"> 
     Test Alert 
    </button> 
    <button class="button button-positive" ng-click="showAlert1()"> 
     Alert1 
    </button> 
    <button class="button button-positive" ng-click="showAlert2()"> 
     Alert2 
    </button> 

    <script id="popup-template.html" type="text/ng-template"> 
     <input ng-model="data.wifi" type="text" placeholder="Password"> 
    </script> 
    </body> 
</html> 

затем в JS:

angular.module('mySuperApp', ['ionic']) 
.controller('PopupCtrl',function($scope, $ionicPopup) { 

    $scope.testAlert = function() { 
    alert('Alerting!'); 
    }; 

    $scope.showAlert1 = function() { 
    $ionicPopup.alert({ 
     title: 'Don\'t eat that!', 
     template: 'It might taste good' 
    }).then(function() { 
     $scope.testAlert(); 
    }); 
    }; 

    $scope.showAlert2 = function() { 
    $ionicPopup.alert({ 
     title: 'Don\'t eat that!', 
     template: 'It might taste good' 
    }).then(function() { 
     $scope.testAlert(); 
    }); 
    }; 
}); 
Смежные вопросы