一个小练习,效果大概是这样的:五个按钮,鼠标经过某一个按钮的时候,按钮变色,离开后恢复原色。
最开始的JS代码是这样子的————
var btn = document.getElementsByTagName('button');
for (var i = 0; i < btn.length; i++) {
btn[i].onmouseover = function () {
for (var j = 0; j < btn.length; j++) {
btn[j].style.backgroundColor = 'aqua';
}
btn[i].style.backgroundColor = 'white';
}
btn[i].onmouseout = function () {
btn[i].style.backgroundColor = 'aqua';
}
}
但是这个没能达到想要的效果,反而调试控制台在鼠标经过按钮与离开按钮时分别提示了这样一条ERROR信息:
Uncaught TypeError: btn[i] is undefined
在JS里面,提示undefined的时候,即为这个东西没有定义。
数组越界???
于是我尝试在捕获鼠标离开的事件中增加输出i值的语句,果不其然,鼠标离开之后,调试控制台输出i值为5。
懂了,这就把btn[i]改为this
var btn = document.getElementsByTagName('button');
for (var i = 0; i < btn.length; i++) {
btn[i].onmouseover = function () {
for (var j = 0; j < btn.length; j++) {
btn[j].style.backgroundColor = 'aqua';
}
this.style.backgroundColor = 'white';
}
btn[i].onmouseout = function () {
// console.log(i);
this.style.backgroundColor = 'aqua';
}
}
解决方法出来了,这个小练习就做好了。
但是问题还没有结束:为什么我能在鼠标经过和离开的时候捕获到具体是哪一个按钮发生了这一事件,而在事件的处理函数当中无法使用下标引用的方式控制这一按钮呢?
这就涉及到JS的事件处理机制以及执行机制了
我们都知道JS是一门脚本语言,自上而下,即时编译,即时执行。而当涉及到事件的时候,引出了事件处理机制:事件循环——
js遇到异步事件后会先将其挂起,然后执行执行栈的其他任务,当一个异步事件返回结果后,js会将这个事件回调任务加入到一个队列,即事件队列。
被放入事件队列的任务不会立刻执行,而是等执行栈的所有任务都执行完毕,主线程处于闲置状态时,主线程会去查找事件队列是否有任务,如果有则从中取出排在第一位的事件,放到执行栈中,如此反复,形成一个循环,即事件循环。
这就解释了上面的问题:i的值随着JS的执行,最终变成5。而i由0变成5这个过程,我们进行的实际上是注册事件(绑定事件)的过程,这期间使用了i的值来为每一个按钮数组元素注册事件,而并不会处理相应的事件处理部分,这也就是我们需要使用this指针的原因。若是使用i的值进行下标访问,当我们触发鼠标经过和离开这样的异步事件的时候,我们的i值已经随着JS代码的执行完毕而变成了5,所以会出现下标访问数组越界的问题。
参考博文:
https://blog.csdn.net/rongmingye/article/details/116085414
本文相关:
https://blog.csdn.net/u013718730/article/details/90484811