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

lea*_*ine 5 javascript

我正在尝试更好地理解Ember SimpleAuth的Firebase身份验证器:

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));
    }
}
});
Run Code Online (Sandbox Code Playgroud)

有人请解释".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');
        });
    }
}


});
Run Code Online (Sandbox Code Playgroud)

思考?

And*_*aus 9

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

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

通过回调,我的意思是作为参数传递的匿名函数,而不是分配给对象的属性.

这样的函数将被绑定window,即this函数内将返回window.

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

var _this = this;

someMethod(function() {
  console.log(this);  // => window
  console.log(_this); // => Outer scope
});
Run Code Online (Sandbox Code Playgroud)

当您需要访问内部和外部范围时,此方法很好.但是内部范围没什么用处,所以我们可以把它写得更短:

someMethod(function() {
  console.log(this); // Outer scope
}.bind(this));
Run Code Online (Sandbox Code Playgroud)

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

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

_this = this

someMethod ->
  console.log this  # winodw
  console.log _this # Outer scope
Run Code Online (Sandbox Code Playgroud)
someMethod =>
  console.log this     # Outer scope
  console.log ` this ` # You can still access window like ` this `, pun intended
Run Code Online (Sandbox Code Playgroud)

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

foo( () => {
  console.log(this);
});
Run Code Online (Sandbox Code Playgroud)

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

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

有关更多信息.bind(),请参阅MDN上的Function.prototype.bind().