关于这个'的困惑角度'控制器中的关键字'句法

时间:2014-09-08 00:37:10

标签: javascript angularjs

我有一个父控制器UserEditCtrl和一个子控制器EditUserCtrl。在我的父控制器内部,我通过服务提取用户对象:

userMgmtSvc.user(scope.editUserId).then(function(data) {
  this.user = data;
});

然后我想将我的用户对象的属性设置为另一个变量。

this.selectedRoles = this.user.roles;

但这会引发错误:

Cannot read property 'user' of undefined.

我对如何引用使用this设置的对象感到困惑。例如,我如何只是console.log对象?因为console.log('user', this.user);返回undefined:

user undefined

这是父控制器:

(
  function (app) {
    /* @fmt: off */
    'use strict';

    // @fmt:on
    app.controller('UserEditCtrl', ['$scope', '$http', 'userMgmtSvc', 'createUserSvc', 'authSvc', '$state', '$timeout', '$location', '_',
      function (scope, http, userMgmtSvc, createUserSvc, authSvc, state, timeout, location, _) {

      userMgmtSvc.user(scope.editUserId.id || sessionStorage.getItem('editUser')).then(function(data) {
        this.user = data;
        console.log('user', this.user);

      // GET states
      createUserSvc.states().then(function(data) {
          this.states = data;
          console.log(this.states);
      });

      // GET countries
        createUserSvc.countries().then(function(data) {
        this.countries = data;
      });

      // GET roles
      createUserSvc.roles().then(function(data) {
        this.roles = data;
      });

      // GET insurance groups
      createUserSvc.insuranceGroups().then(function(data) {
        this.insuranceGroups = data;
      });

      this.selectedRoles = this.user.roles;
    });

 }]);

}(window.app)
);

1 个答案:

答案 0 :(得分:3)

这是一个非常基本的错误,当您在回调中引用this当前上下文时,您不了解执行上下文并最终在其他位置设置值。

为了避免陷入此问题,当您的控制器启动时,只需将this(控制器实例的上下文)设置为变量并在其上设置所有内容。不要假设this将是什么。

 .controller('crtl',[deps..., function(...) {
       //Set this
       var vm = this; //Always use this cached variable have seen a commonly used name of vm

       //............... 
       //...............
       userMgmtSvc.user(scope.editUserId).then(function(data) {
         vm.user = data;
       });

       //...............
       vm.selectedRoles = vm.user.roles

   }

还有很多其他方法可以使用angular.bind或es5 function.bind来创建绑定函数(函数引用预绑定指定的上下文),但最简单的方法是使用缓存的上下文。

当您使用打字稿时,您可以使用=>(胖箭头)语法,因为ES5模式中的打字稿实际上会转换它。

      userMgmtSvc.user(scope.editUserId).then((data) => {
         this.user = data;
      });

来: -

    var _that = this;
    userMgmtSvc.user(scope.editUserId).then((data) => {
         _that.user = data;
     });
Arrow functions时,

the engines starts supporting the arrow function syntax将成为语言本身的一部分(使用ES6规范)。所以使用ES6你可以安全地写: -

      userMgmtSvc.user(scope.editUserId).then((data) => {
         this.user = data;
      });

Here is an excellent answer that specifically targets this