JavaScript类已定义属性仍报TypeError的解决方法
我编写了一个代表HTML元素的JavaScript类,用于答题程序,包含用户输入答案的文本框、提交判分的按钮,以及显示正误状态的文本。类的构造函数如下:
constructor(correctAnswer) { this.correctAnswer = correctAnswer; this.rootHTMLElement = document.createElement("div"); this.textInputElement = document.createElement("input"); this.textInputElement.type = "text"; this.rootHTMLElement.appendChild(this.textInputElement); this.statusIndicatorElement = document.createElement("span"); this.rootHTMLElement.appendChild(this.statusIndicatorElement); this.button = document.createElement("button"); this.button.innerText = "Mark"; this.rootHTMLElement.appendChild(this.button); this.button.addEventListener("click", this.markSelf); }
按钮事件监听调用的markSelf方法如下:
markSelf() { switch (this.textInputElement.value) { case this.correctAnswer: this.statusIndicatorElement.innerText = "Correct"; break case "": this.statusIndicatorElement.innerText = "Not marked"; break default: this.statusIndicatorElement.innerText = "Incorrect"; break } }
仅构造函数和markSelf方法访问this.textInputElement,但点击按钮时却抛出错误:Uncaught TypeError: this.textInputElement is undefined。请问如何修改代码,实现根据输入内容判断答案正误并更新statusIndicatorElement内容的功能?
事件处理函数执行时,this的指向是触发事件的DOM元素(即点击的按钮),而非类的实例对象。因此在markSelf中访问this.textInputElement时,实际上是在按钮元素上查找该属性,自然会返回undefined。
以下三种方法均可解决this指向问题,任选其一即可:
方法1:在构造函数中绑定this
修改构造函数中的事件监听代码,使用bind()将markSelf的this绑定为类实例:
constructor(correctAnswer) { // ... 原有代码不变 ... this.button.addEventListener("click", this.markSelf.bind(this)); }
bind()会返回一个新函数,其内部this固定为传入的类实例,这样点击按钮时执行的markSelf就能正确访问类的属性。
方法2:使用箭头函数作为事件回调
箭头函数的this继承自外层作用域(此处为构造函数的this,即类实例),因此可以直接用箭头函数包裹markSelf调用:
constructor(correctAnswer) { // ... 原有代码不变 ... this.button.addEventListener("click", () => this.markSelf()); }
点击按钮时,箭头函数会调用this.markSelf(),此时的this就是类实例。
方法3:将markSelf定义为类箭头函数方法
直接把markSelf定义为类的箭头函数属性,这样它的this会始终绑定类实例:
markSelf = () => { switch (this.textInputElement.value) { case this.correctAnswer: this.statusIndicatorElement.innerText = "Correct"; break case "": this.statusIndicatorElement.innerText = "Not marked"; break default: this.statusIndicatorElement.innerText = "Incorrect"; break } }
这种方式下,构造函数中的事件监听代码无需修改,this.markSelf的this已经固定为类实例。
内容的提问来源于stack exchange,提问作者pythonmegapixel

