关于时间设置为0的定时器

时间设置为0时并不会立即执行

正确理解setTimeout的方式(注册事件):
1、有两个参数,第一个参数是函数,第二参数是时间值。
2、调用setTimeout时,把函数参数,放到事件队列中。等主程序运行完,再调用。

for (var i = 0;  i < 3;  i++) {

    setTimeout(function() {
         console.log(i);
    }, 0);

  console.log(i);

}

结果是:0 1 2 3 3 3
setTimeout(function() {
        console.log(1);
}, 0);
console.log(2);

先打印2,后打印1。

事件设置不为0时,可能并不会按时执行

setTimeout(fn, 2000)

我们可以理解为2000之后,再放入事件队列中,如果此时队列为空,那么就直接调用fn。如果前面还有其他的事件,那就等待。
因此setTimeout是一个约会从来都不准时的童鞋。

巧妙利用这个机制

我们进行dom操作可以先绑定事件,然后再去写其他逻辑。

setTimeout(function() {
        console.log(i);
}, 0);
var i = 1;

// 1
因为先执行vari=1,所以并不会报错
window.onload = function() {
        fn();
}
var fn = function() {
        alert('hello')
};

这个是一个项目的运用,dom加载完成后,再获取节点,setTimeout是一个宏任务,它在事件队列里排在了script标签这个宏任务的后面

关于时间设置为0的定时器_第1张图片
aaaaa.png

定时器与块级作用域

但此问题在es6里终结了,因为es6,发明了let。

for (var i = 0; i < 3; i++) {}
console.log(i);

es5中是没有块级作用域的,i可以在for循环体外访问到

有关的面试题目

var i = 0;
setTimeout(function() {
    console.log(i);
}, 0);
console.log(i);
i++;
setTimeout(function() {
    console.log(i);
}, 0);
console.log(i);
i++;
setTimeout(function() {
    console.log(i);
}, 0);
console.log(i);
i++;

根据前面的理解,可以把题目转换为

var i = 0;
console.log(i);
i++;
console.log(i);
i++;
console.log(i);
i++;
setTimeout(function() {
    console.log(i);
}, 0);
setTimeout(function() {
    console.log(i);
}, 0);
setTimeout(function() {
    console.log(i);
}, 0);

结果是0 1 2 3 3 3

定时器与闭包

var fn = function() {
        for (var i = 0; i < 3; i++) {
                setTimeout(function() {
                        console.log(i);
                }, 0);
                console.log(i);
        }
};
fn();

上面的函数跟我们常见另一个例子(div绑定事件)有什么区别:

var fn = function() {
        var divs = document.querySelectorAll('div');
        for (var i = 0; i < 3; i++) {
                divs[i].onclick = function() {
                        alert(i);
                };
        }
};
fn();

点击每个div都会弹出3。道理是一样的。因为alert(i)中的i是fn作用越中的,因而这是闭包。
怎么保证能弹出0,1, 2呢。解决之道:再创建个闭包!!

var fn = function() {
        var divs = document.querySelectorAll('div');
        for (var i = 0; i < 3; i++) {
                divs[i].onclick = (function(i) {
                        return function() {
                                alert(i);
                        };
                })(i);
        }
};
fn();

或者如下的写法:

var fn = function() {
        var divs = document.querySelectorAll('div');
        for (var i = 0; i < 3; i++) {
                (function(i) {
                        divs[i].onclick = function() {
                                alert(i);
                        };
                })(i);
        }
};
fn();

因此原题如果也想setTimeout也弹出0,1,2的话,改成如下:

for (var i = 0; i < 3; i++) {
    setTimeout((function(i) {
        return function() {
            console.log(i);
        };
    })(i), 0);
    console.log(i);
}

本文章只作为自己的学习笔记,如有侵权行为请联系我

你可能感兴趣的:(关于时间设置为0的定时器)