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

How do I determine the Execution Context for a JavaScript callback function?

本文关键字:执行 上下文 函数 回调 何确定 JavaScript      更新时间:2023-09-26

当函数作为对象属性调用时,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 并转移到全局上下文(除非严格模式,或在执行前作为方法附加到新对象), 但我犹豫要不要依赖它,因为它不仅仅是猜测。

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

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

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

没有。函数本身根本没有任何执行上下文。

只有在调用函数时才会创建执行上下文。只有函数的调用方式才能确定执行上下文的属性,例如其this值。

例如

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

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

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

对于其他替代方案,请查看 MDN 对 this 关键字的引用。

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

谁能帮助我理解为什么回调是在全局上下文中而不是在父对象的上下文中执行的?

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