如何确定JavaScript回调函数的执行上下文?

时间:2014-11-17 23:31:13

标签: javascript

将函数作为对象属性调用时,this将设置为父对象。有一些类似的规则适用于将函数作为构造函数或事件处理程序调用,但是在浏览了JS Scope上的更多文章之后,并且深入研究了ECMA5.1规范,我一直无法排序当函数作为回调传递时,究竟如何设置执行上下文。

此代码清楚地表明,即使在同一对象中,作为回调传递给另一个方法的方法也会恢复为全局执行上下文(在浏览器和Node.js中)。

var name = 'global';
var self = function() {
    return this.name;
}
var cback = function(ff) {
    return ff();
}
var parent = {
    name: 'parent',
    cback: function(ff) {
        return ff();
    },
    self: function() {
        return this.name;
    }
}
console.log(parent.cback(parent.self));  // Returns "global"

任何人都可以帮助我理解 为什么 回调是在全局上下文中而不是在parent对象的上下文中执行的?我最好的猜测是,作为参数传递的任何函数在将其分配给局部变量(在上面的示例中为ff)时都会替换其先前的执行上下文,这意味着调用它会传递未定义的thisArg和devsc全局上下文(除了严格模式,或者在执行之前作为一个方法附加到一个新对象),但我不愿意依赖它而不是一个猜测。

2 个答案:

答案 0 :(得分:2)

  

当函数作为回调传递时如何设置执行上下文

我认为理解的关键是这些过程是完全独立的。

  

作为参数传递的任何函数在将其分配给局部变量时都会替换其先前的执行上下文

不是真的。函数本身根本没有任何执行上下文。

执行上下文仅在调用函数时创建。并且只有函数的调用方式决定了执行上下文的属性,例如this值。

例如,

  

当一个函数被调用为对象属性时,this被设置为父对象。

,例如parent.cback(…)。被调用的函数由属性引用,基本引用(parent)将成为调用的this上下文。

或者,当函数作为普通函数调用时,this设置为undefined(或以草率模式设置的全局对象) - 例如ff()

对于其他选择,请查看MDN refernce on the this keyword

答案 1 :(得分:1)

回调中this的规则与非方法函数的规则相同。真正重要的是,如果函数调用看起来像f()(非方法),x.f()(方法调用)或new f()(构造函数)

  

任何人都可以帮助我理解为什么回调是在全局上下文中而不是在父对象的上下文中执行的?

可悲的是,这是我们必须忍受的那些大Javascript疣之一。也就是说,如果你在严格模式下运行,thisnull而不是全局对象,这更加理智。此外,在ES6中将有"fat arrow" => lambdas,它从词法上下文继承this(这意味着它从外部函数获取this,就像常规变量一样)