You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么将函数作为回调传递时this的指向会发生改变?

JavaScript this指向问题底层逻辑及解决方案

一、现象底层运行逻辑解释

JavaScript中this的指向遵循运行时绑定规则,和函数定义的位置无关,只和函数的调用方式有关,对应到你的代码场景:

  1. 执行foo.sayName()时,属于「隐式绑定」规则:函数作为对象的方法调用时,this会指向调用该方法的对象,所以此时this指向foo实例,读取this.name拿到foo,输出符合预期。
  2. 执行bar.setCb(foo.sayName)时,你只是把sayName函数本身的引用作为参数传递,这个函数已经和原宿主对象foo失去了关联,相当于把一个独立的函数赋值给了bar.cb属性。
  3. 执行bar.callCb()时,内部调用this.cb(),此时this.cb的调用上下文是bar实例,this指向bar,而Bar构造函数没有为实例定义name属性,所以this.name读取结果为undefined,你的初步判断完全正确。

二、其他更优解决方案

除了你提到的匿名函数包裹方案外,还有以下几种常用的更规范的解决方案:

  • 使用bind显式绑定this
    这是最符合语义、最常用的方案,Function.prototype.bind会返回一个新的硬绑定函数,新函数的this会被永久绑定为你传入的第一个参数,不受后续调用方式影响,稳定性更高:
    bar.setCb(foo.sayName.bind(foo));
    
  • 使用ES6箭头函数
    箭头函数没有自己的this,它的this继承自外层词法作用域的this,写法比普通匿名函数更简洁:
    bar.setCb(() => foo.sayName());
    
  • 修改Bar的callCb方法指定调用上下文
    如果业务逻辑允许固定回调的调用对象,可以在callCb内部用call/apply指定this,适合回调上下文固定的场景:
    Bar.prototype.callCb = function (ctx) {
      this.cb.call(ctx);
    };
    // 调用时传入期望的this指向
    bar.callCb(foo);
    

内容的提问来源于stack exchange,提问作者Stephen R Chen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 18:48:04