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

JavaScript对象方法作为事件回调时this返回undefined的问题咨询

问题解析与解决方案

你遇到的这个问题是JavaScript中this绑定规则的经典场景,我来帮你理清楚原因和解决办法:

为什么会输出undefined?

当你把this.getFoo作为回调函数传给window.addEventListener时,本质上是把getFoo函数的引用单独传递给了事件监听机制。当scroll事件触发时,浏览器会在window的上下文环境中调用这个函数,此时this就指向了window对象。而window上并没有foo属性,所以console.log(this.foo)自然输出undefined。

简单来说:普通函数的this指向是由调用它的方式决定的,而不是定义它的位置。

几种可行的解决方案

方案1:用箭头函数包裹回调(最简洁)

箭头函数的this是继承自它定义时的外层作用域,不会被调用方式改变。在你的method里,外层作用域的this指向myObj,所以用箭头函数包裹getFoo调用就能保证this正确:

let myObj = {
  foo: "bar",
  getFoo: function() { console.log(this.foo); },
  method: function() {
    if (true) {
      // 箭头函数继承method里的this(即myObj)
      window.addEventListener('scroll', () => this.getFoo());
    } else {
      window.removeEventListener('scroll', () => this.getFoo());
    }
  }
}
window.addEventListener('click', () => { myObj.method(); });

⚠️ 注意:如果需要移除事件监听,这种方式每次都会生成新的箭头函数,所以remove的时候无法匹配到之前添加的回调。如果你的代码需要支持移除事件,建议用下面的方案2。

方案2:用bind绑定this(适合需要移除事件的场景)

bind方法会返回一个新函数,这个函数的this会被永久绑定到你指定的对象上。为了保证添加和移除的是同一个函数,最好把绑定后的函数存到对象的属性里:

let myObj = {
  foo: "bar",
  getFoo: function() { console.log(this.foo); },
  // 存储绑定后的函数,避免每次bind生成新函数
  boundGetFoo: null,
  method: function() {
    // 首次调用时绑定this
    if (!this.boundGetFoo) {
      this.boundGetFoo = this.getFoo.bind(this);
    }
    if (true) {
      window.addEventListener('scroll', this.boundGetFoo);
    } else {
      window.removeEventListener('scroll', this.boundGetFoo);
    }
  }
}
window.addEventListener('click', () => { myObj.method(); });

这样添加和移除的是同一个函数引用,就能正确移除事件监听了。

方案3:把getFoo改成箭头函数(需谨慎使用)

如果把getFoo定义成箭头函数,它的this会继承自定义时的外层作用域(这里是全局作用域,即window),所以这种方式不能直接用在对象字面量里——因为对象字面量不会形成新的作用域,箭头函数的this还是指向window,依然拿不到myObj.foo。除非你是在类或者闭包中定义对象,外层作用域的this指向对象本身,否则不推荐这种方式。


内容的提问来源于stack exchange,提问作者galingong

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:24:09