为了账号安全,请及时绑定邮箱和手机立即绑定

为什么for循环中直接使用tr[i]不可以,而将onmouseover等包含到一个函数中调用就可以了?(详情见下面代码)

  • 方式1(无法实现好的效果)

window.onload = function(){
     // 鼠标移动改变背景,可以通过给每行绑定鼠标移上事件和鼠标移除事件来改变所在行背景色。
        var tr = document.getElementsByTagName("tr");
        for(var i = 0; i < tr.length; i++)
        {
           tr[i].onmouseover=function()
            {
                tr[i].style.backgroundColor = "#f2f2f2";
            }
            tr[i].onmouseout=function()
            {
                tr[i].style.backgroundColor = "#fff";
            }      

       }
}

  • 方法二(可以实现):

window.onload = function(){
                  
     // 鼠标移动改变背景,可以通过给每行绑定鼠标移上事件和鼠标移除事件来改变所在行背景色。
     var tr = document.getElementsByTagName("tr");
     for(var i = 0; i < tr.length; i++)
     {
     ch(tr[i]);
     }
        
     function ch(obj)
     {
          obj.onmouseover=function()
            {
                obj.style.backgroundColor = "#f2f2f2";
            }
            obj.onmouseout=function()
            {
                obj.style.backgroundColor = "#fff";
            }
     }
}

正在回答

5 回答

这是由于事件的异步执行造成的。方法一中给每个tr都绑定了onmouseover和onmouseout事件,页面加载完成后,for循环中的i已经变为了tr.length。而事件此时还没有被触发,当用户移动鼠标触发事件时,事件函数中的代码  tr[i].style.backgroundColor = "#f2f2f2";开始执行,而这时i的值已经是tr.length了,tr[i]即tr[tr.length],可tr中最后一个是tr[tr.length-1],而tr[tr.length]这个节点是不存在的。

5 回复 有任何疑惑可以回复我~
#1

qq_普通人_1

"页面加载完成后,for循环中的i已经变为了tr.length",这句话怎么理解?
2015-10-18 回复 有任何疑惑可以回复我~
#2

大柏树 回复 qq_普通人_1

假设一共有3个tr,即tr.length=3吧。方法一页面加载时, for(var i = 0; i < tr.length; i++)这个循环开始执行,为tr[0]的onmouseover绑定了 tr[i].style.backgroundColor = "#f2f2f2";这个背景色事件;循环继续执行,i变为1,为tr[1]的onmouseover绑定了 tr[i].style.backgroundColor = "#f2f2f2";这个背景色事件;一直到i变为3时,i < tr.length这个循环条件不成立,继续执行下面的代码,此时变量i的值已经变为3了。
2015-10-19 回复 有任何疑惑可以回复我~
#3

大柏树 回复 qq_普通人_1

页面加载完成后,此时鼠标划过上面的任何一个tr,都会触发这个tr的onmouseover事件,即tr[i].style.backgroundColor = "#f2f2f2",而此时的i=3,所以任何一个tr的onmouseover事件都是tr[3].style.backgroundColor = "#f2f2f2",因为只有3个tr,tr[3]指的是第四个tr,是不存在的。所以事件触发后没有反应,而且控制台会报错。如果把这句tr[i].style.backgroundColor = "#f2f2f2"改为this.style.backgroundColor = "#f2f2f2",就可以了。
2015-10-19 回复 有任何疑惑可以回复我~
#4

大柏树 回复 qq_普通人_1

同步指的是页面加载时,代码依次执行。可以认为页面是瞬间加载完成的,在这之后执行的代码可以认为是异步。如Ajax,绑定事件,setTimeout,setInterval等。
2015-10-19 回复 有任何疑惑可以回复我~
#5

qq_普通人_1 回复 大柏树

谢谢你的回答。有点不好理解,我再查查资料
2015-10-19 回复 有任何疑惑可以回复我~
#6

wolf3c 提问者

讲的非常透彻。
2015-11-26 回复 有任何疑惑可以回复我~
#7

慕容7796276

我有一个地方不懂就是for循环结束后,每个tr[i]的事件不是已经注册了吗?就是tr[0].style.backgroundColor = "#f2f2f2";这样每个tr[i]事件都注册了,那这时i怎么变不是应该没关系了吗,为什么鼠标移动的时候触发事件的时候还要在执行tr[i].style.backgroundColor = "#f2f2f2";这个啊,不是应该执行如tr[0].style.backgroundColor = "#f2f2f2";这样的
2016-11-10 回复 有任何疑惑可以回复我~
#8

Jhin_3353147 回复 慕容7796276

有同样的疑问,不过也不是不能理解,在题主的方法一中,绑定事件里的tr[i]没有被触发是不会把变量i代进去的,在触发事件的时候才把i代入,方法二中ch(obj)方法执行了三次,每次obj都是一个明确的变量。
2016-11-28 回复 有任何疑惑可以回复我~
#9

Jhin_3353147 回复 慕容7796276

其实很简单,只要在方法里面console tr[i]出来,就知道了。
2016-11-28 回复 有任何疑惑可以回复我~
#10

millia 回复 大柏树

大神: for(var i = 0; i < tr.length; i++) { ch(tr[i]); } 想问一下ch(tr[i]);是什么意思啊?
2019-06-13 回复 有任何疑惑可以回复我~
查看7条回复

为什么i=3的时候循环不成立,还执行下面的代码?

1 回复 有任何疑惑可以回复我~
#1

Jhin_3353147

不是这样看的。 在i<3的时候才会执行里面的代码,就是:为tr[i]添加绑定事件。 i=3的时候循环不成立,不执行里面的代码,即:不为tr[3]添加绑定事件。 但是当鼠标悬浮的时候,触发的是已绑定过的事件,而不是很for循环里的代码。 没毛病
2016-11-28 回复 有任何疑惑可以回复我~

像参考答案里用this指向当前对象就行了,你那个obj也是同样道理

0 回复 有任何疑惑可以回复我~

你在第一个里面for循环里面alert(tr[i]),会返回[object HTMLTableRowElement],HTMLTableRowElement是一个接口,这个我也不清楚,反正他不是一个正常的对象,你还可以用另一种方式验证他的类型,就是你在alert(arr[2] instanceof Object),会返回false,说明他并不是一个Object,所以第一个会调用失败。

第二个function里面你把tr[i]当做参数传入,参数的类型是any,也就是说他可以是任意的类型,使用的时候当做Object使用,在这过程中参数类型发生了变化


0 回复 有任何疑惑可以回复我~
#1

wolf3c 提问者

谢谢~虽然看起来很多东西我还不了解,但是至少大概明白了自己为什么错了。
2015-09-14 回复 有任何疑惑可以回复我~

举报

0/150
提交
取消

为什么for循环中直接使用tr[i]不可以,而将onmouseover等包含到一个函数中调用就可以了?(详情见下面代码)

我要回答 关注问题
意见反馈 帮助中心 APP下载
官方微信