我正在努力更好地理解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');
});
}
}
});
思想?
答案 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。