JavaScript对象方法调用时this未按预期绑定为undefined问题
核心原因
JavaScript普通函数的this绑定规则和函数定义位置无关,完全由函数最终的调用方式决定,这是两段相似代码运行结果不一致的根本原因。
能正常取到this的调用逻辑
最开始写的链式调用写法:
console.log(foo(({type, partitionName})=>console.log(partitionName)).onSelect()) // 预期输出 "Personal Files"
属于标准的对象方法调用:onSelect直接挂载在foo()返回的对象上,通过对象.方法()的形式执行,这种场景下this会自动绑定到.前面的对象实例,也就是定义的带name: "Personal Files"属性的对象,和官方文档示例里test.func()的调用逻辑完全一致,这种写法下不会出现this为undefined的问题。
触发this为undefined的实际场景
实际运行时的写法是先把对象方法单独赋值给变量再执行:
const bar = foo(({type, partitionName})=>console.log(partitionName)).onSelect console.log(bar()) // 实际this为undefined
这时候bar是脱离了原对象的独立函数,直接执行独立函数时,在现代JS默认开启的严格模式下,函数内部的this默认就是undefined,自然无法读取name属性。
注意:写在对象字面量里的方法不会永久绑定所属对象,只要把方法单独拆出赋值、作为回调参数传递,都会丢失原本的对象上下文绑定,这是JS的原生设计,不是代码逻辑写错了。
可选解决方案
- 方法1:返回对象时提前绑定固定this,避免后续拆出时丢失:
const foo = (dispatch) => { const res = { name: "Personal Files", onSelect: function() { dispatch({ type: MoveDocActionType.ENTER_PARTITION, partitionName: this.name }) } } res.onSelect = res.onSelect.bind(res) return res }
- 方法2:直接用闭包存值,完全规避this绑定问题,是更不容易出bug的写法:
const foo = (dispatch) => { const partitionName = "Personal Files" return { name: partitionName, onSelect: () => { dispatch({ type: MoveDocActionType.ENTER_PARTITION, partitionName }) } } }
- 方法3:如果是在框架里传事件回调,可以在传参时临时包一层箭头函数,保持原对象调用形式:
// 以React场景为例,不要直接传obj.onSelect <button onClick={() => obj.onSelect()}></button>
内容的提问来源于stack exchange,提问作者Jordan Mackie
相关产品推荐
相关产品推荐

