>  Q&A  >  본문

javascript - Js遍历元素并赋予事件绑定匿名函数时,为什么调试说未定义元素?

表格鼠标悬停变色。
代码:

     var tr=document.getElementsByTagName('tr');
     for (var i = 0; i < tr.length; i++) {
         tr[i].onmouseover=function(){
             tr[i].style.backgroundColor="#f2f2f2";
         }
         tr[i].onmouseleave=function(){
             tr[i].style.backgroundColor="#fff";
         }
     }

chrome说的是 Uncaught TypeError: Cannot read property 'style' of undefined at HTMLTableRowElement.tr.(anonymous function).onmouseover

但是把tr[i]改为this就可以:

         var tr=document.getElementsByTagName('tr');
         for (var i = 0; i < tr.length; i++) {
             tr[i].onmouseover=function(){
                 this.style.backgroundColor="#f2f2f2";
             }
             tr[i].onmouseleave=function(){
                 this.style.backgroundColor="#fff";
             }
         }     
PHP中文网PHP中文网2728일 전810

모든 응답(6)나는 대답할 것이다

  • 天蓬老师

    天蓬老师2017-04-11 12:05:05

    让我们先来假设页面上有5个tr,这样子比较好说明:

    var tr=document.getElementsByTagName('tr');
    for (var i = 0; i < tr.length; i++) {   
        tr[i].onmouseover = function on_tr_over() {
            tr[i].style.backgroundColor="#f2f2f2";
        };
    }
    
    // 因为你页面上的鼠标事件触发是在for循环之后的
    // 这时候i的赋值是tr.length,也就是i是5
    // 这5个tr分别是tr[0]到tr[4],tr[5]是代表第6个tr元素了
    // 而实际上页面上没有第6个tr,所以就是undefined了
    // 当鼠标移到tr时,相当于执行下面的语句:
    tr[5].style.backgroundColor="#f2f2f2"; // 调了undefined的style属性,所以报错了哦

    而第二段代码传this的话,就是指向事件被触发的目标元素,这个是浏览器传给你了,所以一定正确

    哈哈,这是形象的理解,希望对你有帮助。

    회신하다
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-11 12:05:05

     var tr=document.getElementsByTagName('tr');
     for (var i = 0; i < tr.length; i++) {
         tr[i].onmouseover=function(){
             tr[i].style.backgroundColor="#f2f2f2";
         }
         tr[i].onmouseleave=function(){
             tr[i].style.backgroundColor="#fff";
         }
     }

    翻译一遍运行过程:

    1. 获取所有tr元素

    2. 遍历所有tr元素给他们绑定两个事件

    3. 循环结束,此时i值为tr.length

    4. 当移入某一个时,触发事件,去寻找tr[tr.length],得到的是undefined

    5. 当undefined.style时报错

    회신하다
    0
  • 怪我咯

    怪我咯2017-04-11 12:05:05

    这个问题是闭包变量引用的问题, @UKer 已经回答得很清楚了。解决办法你已经给了一个,用 this。我再给你一个不用 this 的解决办法吧

    var tr = document.getElementsByTagName("tr");
    for (var i = 0; i < tr.length; i++) {
        (function(index) {
            tr[index].onmouseover = function() {
                tr[index].style.backgroundColor = "#f2f2f2";
            };
            tr[index].onmouseleave = function() {
                tr[index].style.backgroundColor = "#fff";
            };
        })(i);
    }

    회신하다
    0
  • 大家讲道理

    大家讲道理2017-04-11 12:05:05

    函数里的tr[i]是运行时计算的,当循环执行完,这时i就等于tr.length了,再执行绑定的函数,那函数里的tr[i]其实等于tr[tr.length],自然就报错了。解决办法可以使用闭包。

    회신하다
    1
  • PHPz

    PHPz2017-04-11 12:05:05

    楼上正解,等同于tr.length

    회신하다
    0
  • ringa_lee

    ringa_lee2017-04-11 12:05:05

    即便已经采纳答案感觉你还是没GET到点上。这个问题的关键是闭包。
    看一下ES6的let。

    举例:

    
    <html>
    <head></head>
    <body>
    
    <p name="dvTest" style="width: 100px; height: 50px; background-color: #ff0000"></p> 
    <p name="dvTest" style="width: 100px; height: 50px; background-color: #00ff00"></p> 
    <p name="dvTest" style="width: 100px; height: 50px; background-color: #0000ff"></p> 
    <p></p>
    <p name="dvTest2" style="width: 100px; height: 50px; background-color: #ff0000"></p> 
    <p name="dvTest2" style="width: 100px; height: 50px; background-color: #00ff00"></p> 
    <p name="dvTest2" style="width: 100px; height: 50px; background-color: #0000ff"></p> 
    
    <script>
        var dvTest = document.getElementsByName('dvTest');
        var dvTest2 = document.getElementsByName('dvTest2');
    
        for(let i=0; i<dvTest.length; i++)
        {
            dvTest[i].onmouseover=function()
            {
                 console.log(i);
             }
        }
    
    
        for(var k=0; k<dvTest2.length; k++)
        {
            dvTest2[k].onmouseover=function()
            {
                 console.log(k);
             }
        }
    
    
    
    </script>
    </body>
    </html>

    你比较一下let和var来定义for中变量的不同。鼠标滑过前三个色块,看浏览器调试窗口的输出。再滑过后三个色块看看输出什么。

    회신하다
    0
  • 취소회신하다