js是单线程的;
js中的线程分为三种
1.页面渲染
2.主代码逻辑
3.事件触发;
下面我们来看一段代码
<script>
setTimeout(function(){
console.log(123);
},0);
</script>
按照js的api来看,上面的代码应该是0秒后执行,但真的是这样吗?
js中没有控制线程的,所以无法让线程进行睡眠;但我们可以用alert阻塞线程;
当我们在后面加alert后,我们看到,123并没有立刻输出;而是等待弹窗关闭后才输出;
在js中,遇到回调等都会将回调暂时挂起,等待主流程的执行完毕才会执行回调等函数;
看如下代码
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <script> 7 window.onload = function () { 8 var divs = document.getElementsByTagName("div"); 9 for (var i = 0; i < divs.length; i++) { 10 var div = divs[i]; 11 12 div.onclick = function () { 13 alert("我是第"+ (i+1) +"个div"); 14 }; 15 16 } 17 } 18 </script> 19 </head> 20 <body> 21 <div>我是第1个div</div> 22 <div>我是第2个div</div> 23 <div>我是第3个div</div> 24 <div>我是第4个div</div> 25 <div>我是第5个div</div> 26 <div>我是第6个div</div> 27 <div>我是第7个div</div> 28 <div>我是第8个div</div> 29 <div>我是第9个div</div> 30 <div>我是第10个div</div> 31 </body> 32 </html>
很多人应该都知道上面的代码不会按照我们的本意进行执行,但你们能说清楚为什么吗?
现在我们来分析一下;
div.onclick = function () {
alert("我是第"+ (i+1) +"个div");
};
后面的方法并不会立刻执行,这是我们都理解的,div.onclick指向了一个方法对象,这个方法对象被放在一个地方(挂起)
前一节我们说过了,js中没有块级作用域,所以在for里面定义的i等于在for外面定义的;
window.onload = function () {
var divs = document.getElementsByTagName("div");
var i;
for ( i= 0; i < divs.length; i++) {
var div = divs[i];
div.onclick = function () {
alert("我是第"+ (i+1) +"个div");
};
}
}
由上我们可以看出,当for循环完毕后,i为divs的长度,而当div点击事件触发的时候,方法会向上级查找i变量,此时的i已经不是循环时的i了;
这时候我们可以通过闭包的形式来解决上面的问题;
window.onload = function () {
var divs = document.getElementsByTagName("div");
for (var i = 0; i < divs.length; i++) {
var div = divs[i];
div.onclick = (function (j){
return function () {
alert("我是第"+ (j+1) +"个div");
};
})(i);
}
}
原理就是将循环时的i保存起来,以备后期方法调用的使用使用;