一.JS的执行特点
源于单线程的特性, JS在一段时间内只能执行一部分代码, 那么, 当有多块代码需要执行时, 就需要排队等候了.
二.单线程与异步事件
(1) 什么是异步事件?
异步事件是像鼠标点击、计时器释放、XMLHttpRequest请求完成这样的动作, 由于我们不知道它何时执行, 所以, 可以认为它是不同步的(这些说明只能作为帮助理解的参考, O(∩_∩)O).
(2) 异步事件是否会受到单线程的影响?
答案是肯定的: 异步事件也必须排队等候(即异步事件对应的JS回调函数, 也必须排队等候执行, 如何排队则因浏览器而异).
我们经常借助setTimeout来"改善恶劣的等候情况", 这里就以一个setTimeout的例子, 来展示一下单线程独特的魅力:
// code
<script type="text/javascript">
function ShowCurrentTime(){
var date = new Date();
var now = "";
now = date.getFullYear()+"-";
now = now + (date.getMonth()+1)+"-";
now = now + date.getDate()+" ";
now = now + date.getHours()+":";
now = now + date.getMinutes()+":";
now = now + date.getSeconds();
return now;
}
function test(){
console.log('a_time:' + ShowCurrentTime());
//访问该连接会延迟12秒
$.post('http://www.xxxxx.com/oilcard/index','',function(){
console.log('b_time:' + ShowCurrentTime());
},'html');
console.log('c_time:' + ShowCurrentTime());
}
test();
setInterval("console.log('d_time:' + ShowCurrentTime())", 1000 );
</script>
// 执行结果
执行先后:a,c,d,b ;
// 对执行结果的分析
从结果可以很明显的看到, 延时函数是在add函数执行完之后才执行的, 为什么会这样呢? 这是因为,
timeout只延时了15ms, 而add函数执行所需的时间远大于15ms, 也就是说, 在add函数还未执行完毕
时, 计时器就已经释放了, 但是由于单线程的原因, 延时函数不会立即执行(因为当前时间段内, add函数还在执行), 而此时, 浏览器会将延时函数编入队列, 以便能在下一个可执行的时间段内得到执行.(过程如下图)
再来个例子:
去掉上面的延迟12秒响应;
结果:
执行先后是: acbd;
你看,就代码块来说,在同一个作用域里的代码优先执行。
后面才执行的D;
后面才执行的D;
同样类似的例子在php中,无法重现,绝对的按语言优先级来。