JS类构造器定义的this.mode在事件绑定方法中报未定义错误
报错核心原因
这不是this.mode属性没有被正确挂载到类实例上,本质是DOM事件回调的this指向和Editor类实例完全脱钩了。
逐段逻辑对应
- 构造函数阶段的执行逻辑是完全正常的
构造函数执行时,上下文的this就是当前创建的Editor类实例,这行this.mode = document.querySelector('input[name="preview_mode"]:checked')确实把选中的单选框元素正确挂到了实例上。紧随其后的console.log(this.mode.value)能正常输出预期值,也直接验证了这个赋值流程没有问题。 - 报错的触发根源在事件绑定的这行代码:
这里直接把类的原型方法摘出来,赋值给了DOM元素的事件触发属性。当后续用户在输入框触发oninput事件时,浏览器执行回调的默认规则是:把回调的this.note_text.oninput = this.display_update;this指向触发事件的DOM元素本身,也就是id为note_text的输入框元素。
此时在display_update里写的this.mode.value,实际是在尝试读取输入框元素上名为mode的属性——原生DOM元素不存在这个自定义属性,自然就抛出了this.mode is undefined的错误。
容易踩的认知误区:很多人会默认类方法内部的this永远绑定类实例,实际上JS的this是由函数的调用方式决定的,和函数定义在类的哪个位置没有绝对绑定关系。只要函数脱离了类实例的上下文被单独调用,this就会指向新的执行上下文。
可直接使用的修复方案
- 方案1:给事件绑定套一层箭头函数,锁定类实例的词法作用域
修改构造函数内的事件绑定逻辑即可:
箭头函数没有自身的this,会沿着词法作用域向上找到构造函数执行时的Editor实例上下文,保证调用this.note_text.oninput = () => this.display_update();display_update时,方法内部的this依然指向类实例。 - 方案2:在构造函数内给方法做硬绑定,永久锁定this指向
在构造函数的初始化阶段增加绑定逻辑:
这种方式会把this.display_update = this.display_update.bind(this); // 原来的事件绑定代码可以保持不变 this.note_text.oninput = this.display_update;display_update方法的this永久绑定为当前的Editor实例,后续不管把这个方法作为回调赋值给任何DOM事件、定时器,触发时的this都不会发生偏移。
内容的提问来源于stack exchange,提问作者vkubicki
相关产品推荐
相关产品推荐

