JavaScript用class实现模态框报错Uncaught TypeError: this.hide is not a function
问题根因
报错的核心原因是事件回调函数的this指向错误:
- 你给
this.modal绑定点击事件时用了普通匿名函数,普通函数作为DOM事件回调时,内部的this默认指向触发事件的DOM元素(也就是你的模态框节点本身),而非Modal类的实例,自然找不到实例上的hide方法。 - 你提前做的
this.hide = this.hide.bind(this)操作是正确的,但因为回调里的this根本不是类实例,所以调用的压根不是你绑定过的方法。
解决方案
有两种常用的修复方式:
方式1:将事件回调改为箭头函数(推荐)
箭头函数没有独立的this,会继承外层作用域的this(也就是constructor里的类实例),修改事件绑定代码即可:
// 把原来的普通函数回调换成箭头函数 this.modal.addEventListener("click", (event) => { this.hide(); // 你原来注释的判断逻辑也可以正常用:if (event.target === this.modal) {} })
你被注释的其他事件监听(比如关闭按钮点击、模态框背景点击)都存在同样的this指向问题,统一换成箭头函数即可正常工作。
方式2:提前缓存类实例指向
如果不想使用箭头函数,可以在constructor顶部把类实例的this存到临时变量中,回调里直接用该变量调用方法:
constructor(modalNode) { const _this = this; // 缓存实例指向 this.modal = modalNode; // ...其他代码 this.modal.addEventListener("click", function (event) { _this.hide(); // 用缓存的实例调用方法 }) }
修正后的完整代码
class Modal { constructor(modalNode) { this.modal = modalNode; this.modalsButton = document.querySelectorAll("button.modal"); this.hide = this.hide.bind(this); for (let i = 0; i < this.modalsButton.length; i++) { let value = searchAttributeValue(this.modalsButton[i], "data-toggle"); if (value !== "undefined") { this.modalsButton[i].addEventListener("click", (event) => { let value = searchAttributeValue(event.target, "data-toggle"); if (value !== "undefined") { document.querySelector(value).style.display = "block"; } }); } } // 这里改为箭头函数 this.modal.addEventListener("click", (event) => { this.hide(); // 保留你原来的判断逻辑也可以正常运行 /*if (event.target === this.modal) { event.target.style.display = "none"; }*/ }) // 下面注释的代码如果要启用,同样把回调改为箭头函数即可 /*for (let i = 0; i < this.modals.length; i++) { this.modals[i].addEventListener("click", (event) => { if (event.target === this.modals[i]) { event.target.style.display = "none"; } }); let button_close = this.modals[i].querySelector("button.close[data-toggle=close]"); button_close.addEventListener("click", (event) => { this.modals[i].style.display = "none"; }) }*/ } hide() { this.modal.style.display = "none"; } } modals = document.querySelectorAll("div.modal"); for (let i = 0; i < modals.length; i++) { new Modal(modals[i]); }
内容的提问来源于stack exchange,提问作者Christophe DALOZ - DE LOS RIOS
相关产品推荐
相关产品推荐

