在Ember函数上绑定'this'会发生什么?

时间:2015-06-28 13:16:06

标签: javascript

我正在努力更好地理解this Firebase authenticator for Ember SimpleAuth

import Ember from 'ember';


export default Ember.Controller.extend({


actions: {
    login: function() {
        this.get('session').authenticate('authenticator:firebase', {
            'email': this.get('email'),
            'password': this.get('password')
        }).then(function() {
            this.transitionToRoute('index');
        }.bind(this));
    },
    logout: function() {
        this.get('session').invalidate().then(function() {
            this.transitionToRoute('login');
        }.bind(this));
    }
}
});

有人请解释“.bind(this)”正在做什么,以及在这个特定实例中究竟绑定是如何工作的?

编辑:经过一番反思和研究后,我提出了对可能发生的事情的解释:

代码的“.then”部分无法访问“this”的原始上下文。 “.bind(this)”将“this”(在本例中为当前控制器对象)的值设置为“.then”函数内的“this”。

这可以通过以下事实来证明:如果删除“.bind(this)”部分,则代码的“transitionTo”部分不起作用。

另一方面,如果我们编写如下代码,我们不需要使用 “.bind(this)”:

import Ember from 'ember';


export default Ember.Controller.extend({


actions: {
    login: function() {
    var _this = this;
        this.get('session').authenticate('authenticator:firebase', {
            'email': this.get('email'),
            'password': this.get('password')
        }).then(function() {
            _this.transitionToRoute('index');
        });
    },
    logout: function() {
      var _this = this; 
        this.get('session').invalidate().then(function() {
            _this.transitionToRoute('login');
        });
    }
}


});

思想?

2 个答案:

答案 0 :(得分:9)

  

当你绑定这个'时会发生什么?在Ember函数上?

在您的示例中,Ember函数不使用.bind()。它用于通常的匿名函数(回调)。因此,你的问题与Ember无关。

回调是指作为参数传递的匿名函数,而不是分配给对象的属性。

这样的功能将绑定到window,i。即函数中的this将返回window

访问外部作用域的传统方法是将this分配给外部作用域中的变量,然后访问内部作用域中的变量:

var _this = this;

someMethod(function() {
  console.log(this);  // => window
  console.log(_this); // => Outer scope
});

当您需要访问内部和外部范围时,此方法很好。但是在内部范围内没有任何用处,所以我们可以写得更短:

someMethod(function() {
  console.log(this); // Outer scope
}.bind(this));

.bind()方法在anon函数的外部作用域中执行。它将函数绑定到外部范围。因此,函数的内部范围将与外部范围相同,并且您可以像往常一样使用this,就像示波器没有改变一样。

在CoffeeScript中,您可以使用胖箭头保留在外部范围内:

_this = this

someMethod ->
  console.log this  # winodw
  console.log _this # Outer scope
 
someMethod =>
  console.log this     # Outer scope
  console.log ` this ` # You can still access window like ` this `, pun intended

在ES6中你也可以使用胖箭头:

foo( () => {
  console.log(this);
});

请注意,虽然在CoffeeScript中胖箭头保持外部范围,但它意味着不同的东西!在ES6中,胖箭头创建了一个无法拥有自己范围的虚假函数。

这很重要,因为有些库通过将回调应用到某个范围来与回调进行通信,并希望您对其进行this.something()。它不会使用ES6胖箭(好吧,它可以在技术上与Babel一起工作,因为Babel将ES6胖箭转换为传统功能,但你不应该依赖它)。

有关.bind()的详情,请参阅Function.prototype.bind() on MDN

答案 1 :(得分:3)

这正是发生的事情。如果您 .bind(此),则无需在函数外部为创建别名。有关详细说明,请参阅this question