JS新手求助:表格镜像场景下匿名函数事件监听器报TypeError(toggle未定义)
嘿,我来帮你搞定这个问题!
首先,你遇到的TypeError: toggle未定义错误,核心原因很明确:toggle不是全局函数,也不是DOM元素本身的方法——它是元素的classList对象的专属方法,你得通过this.classList.toggle('你的类名')来调用,直接写toggle()的话,JS会以为你在调用一个没定义的全局函数,自然就报错了。
先回顾下你的Case1为什么能正常运行,完整代码应该是这样的(补全你没写完的部分):
var table1td = document.querySelectorAll("#table1 td"); var table2td = document.querySelectorAll("#table2 td"); for(var i=0; i<table2td.length; i++) { table2td[i].addEventListener("click", _click); } function _click() { // 切换当前点击td的类 this.classList.toggle('active'); // 找到当前td的索引,同步table1对应位置的td状态 const index = Array.from(table2td).indexOf(this); table1td[index].classList.toggle('active'); }
这里的命名函数_click里,this默认指向触发点击的<td>元素,通过this.classList.toggle调用方法完全没问题,而且用Array.from(table2td).indexOf(this)获取索引也避开了循环闭包的坑。
那你写Case2的时候,大概率是不小心把this.classList.toggle写成了toggle(),或者误写了this.toggle()(元素本身没有toggle方法)。下面给你正确的匿名函数版本代码,分两种情况:
情况1:用ES5语法(兼容旧浏览器)
需要用立即执行函数保存循环的索引,避免闭包导致的索引错乱:
var table1td = document.querySelectorAll("#table1 td"); var table2td = document.querySelectorAll("#table2 td"); for(var i=0; i<table2td.length; i++) { // 立即执行函数把当前循环的i值存为index (function(index) { table2td[index].addEventListener("click", function() { // 切换当前td的类 this.classList.toggle('active'); // 同步table1对应位置的td table1td[index].classList.toggle('active'); }); })(i); }
情况2:用ES6语法(更简洁)
如果你的项目支持ES6,直接用let声明循环变量就行,let的块级作用域会自动帮你保存每个循环的索引值:
const table1td = document.querySelectorAll("#table1 td"); const table2td = document.querySelectorAll("#table2 td"); for(let i=0; i<table2td.length; i++) { table2td[i].addEventListener("click", function() { this.classList.toggle('active'); table1td[i].classList.toggle('active'); }); }
这样写出来的匿名函数版本就能正常实现表格镜像的点击效果啦,再也不会报toggle未定义的错误了~
内容的提问来源于stack exchange,提问作者user7171623
相关产品推荐
相关产品推荐

