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>
View Code

很多人应该都知道上面的代码不会按照我们的本意进行执行,但你们能说清楚为什么吗?

现在我们来分析一下;

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保存起来,以备后期方法调用的使用使用;