JavaScript运行机制详解

 
var test = function(){
alert("test");
}
var test2 = function(){
alert("test2");
}
setTimeout(function(){
alert("setTimeout");
},1000);
test();
test2();
//test
//test2
//setTimeout;

上面代码的运行结果一直让我很费解,为什么test()test2()没有在setTimeout()之后才执行,相当于先执行了定时器外面的函数,而后再执行定时器里的函数,这是为什么呢?在解释之前,我们有必要知道JavaScript的运行机制。
***

一、JavaScript为什么是单线程

要回答这个问题,只要我们假设一下,如果JavaScript支持多线程,一个线程在某个DOM节点上添加内容,另外一个线程删除了这个节点,那么浏览器该以哪个线程为准呢?所以答案也就不言而喻了。为了避免复杂性,JavaScript从诞生就是单线程。
在HTML5中,推出了web worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程的控制,且不得操作DOM,所以也是没有违背JavaScript单线程的本质。
***

二、任务队列

因为JavaScript是单线程,意味着任务要一个接着一个完成,但是,如果前一个任务执行时间很长,那么后面的任务就得一直阻塞着,这样用户体验十分差。
JavaScript的设计者考虑到了这一点,所以他将JavaScript的任务分为两种,在主线程上执行的任务"同步任务",被主线程挂载起来的任务"异步任务",后者一般是放在一个叫任务队列的数据结构中。
那么一般异步执行运行机制如下(也是JavaScript的运行机制):

  • (1)所有同步任务都在主线程上执行,形成一个执行栈。
  • (2)主线程之外,还有一个“任务队列”,只要异步任务有了运行结果,就在“任务队列”之中放置一个事件。
  • (3)一旦“执行栈”中的所有同步任务执行完毕了,系统就会读取“任务队列”,看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
  • (4)主线程不断重复上面的三步。(事件循环)

参考图片(图片来源 阮一峰老师讲解的JavaScript运行机制详解)


三、事件和回调函数

看了前面的讲解,我一开始提出的问题视乎可以这样理解,test()test2()属于“执行栈”中的同步任务,而定时器则是任务队列里面的异步任务,那么定时器就是属于异步任务中的一种,在讲定时器之前先认识一下任务队列里面的另外一个重要成员,事件。其实任务队列就是一个事件队列,因为一般我们绑定一个事件,比如点击事件等等,都是在某一个时刻才触发执行的,这个时候就得放到任务队列里面,等待执行,而在某个DOM节点上绑定了事件,就要有相应的回调函数,它们是相辅相成的。
所谓回调函数,就是那些被挂载起来,等待执行的代码,主线程执行任务队列里面的异步任务,其实就是执行这些回调函数。
一般只有主线程所有任务都执行完毕了,才会执行任务队列里面的异步任务,一般是按照队列的“先进先出”顺序执行,但是因为存在定时器,所以主线程要检查执行时间,只有到了规定的时间,才能返回主线程。
***

四、定时器

终于到特殊的定时器了,定时器主要由setTimeout()setInterval()两个函数来完成,它们的内部运行机制完全一样,不同的只是,前者一次性执行,而后者反复执行。定时器,属于任务队列中的异步任务,所以才会出现上面的问题,再看几个例子就能理解了,

console.log(1);
setTimeout(function(){ console.log(2);},1000);
console.log(3);

上面代码的执行结果是1,3,2,因为只有setTimeout里面的代码是异步任务,其它都是主线程里的同步任务,所以只有执行完了主线程中的所有任务,才会执行setTimeout中的任务。

参考:https://www.cnblogs.com/mcray/p/6938417.html

JavaScript运行机制详解的更多相关文章

  1. JavaScript 运行机制详解:再谈Event Loop

    原文地址:http://www.ruanyifeng.com/blog/2014/10/event-loop.html 一年前,我写了一篇<什么是 Event Loop?>,谈了我对Eve ...

  2. JavaScript 运行机制详解:深入理解Event Loop

    Philip Roberts的演讲<Help, I'm stuck in an event-loop>,详细.完整.正确地描述JavaScript引擎的内部运行机制. 一.为什么JavaS ...

  3. javascript运行机制详解: 再谈Event Loop(转)

    作者: 阮一峰 日期: 2014年10月 8日 一年前,我写了一篇<什么是 Event Loop?>,谈了我对Event Loop的理解. 上个月,我偶然看到了Philip Roberts ...

  4. JavaScript 运行机制详解:Event Loop

    参考地址:http://www.ruanyifeng.com/blog/2014/10/event-loop.html 一.为什么JavaScript是单线程? JavaScript语言的一大特点就是 ...

  5. JavaScript 运行机制详解

    一.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊. Java ...

  6. 【repost】JavaScript 运行机制详解:再谈Event Loop

    一年前,我写了一篇<什么是 Event Loop?>,谈了我对Event Loop的理解. 上个月,我偶然看到了Philip Roberts的演讲<Help, I'm stuck i ...

  7. [转] JavaScript 运行机制详解:再谈Event Loop

    一.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊. Java ...

  8. [转载]JavaScript 运行机制详解:再谈Event Loop

    https://app.yinxiang.com/shard/s8/sh/b72fe246-a89d-434b-85f0-a36420849b84/59bad790bdcf6b0a66b8b93d5e ...

  9. 【朴灵评注】JavaScript 运行机制详解:再谈Event Loop

    PS: 我先旁观下大师们的讨论,得多看书了~   别人说的:“看了一下不觉得评注对到哪里去,只有吹毛求疵之感. 比如同步异步介绍,本来就无大错:比如node图里面的OS operation,推敲一下就 ...

随机推荐

  1. 开源数据流管道-Luigi vs Azkaban vs Oozie vs Airflow

    原文链接:https://www.jianshu.com/p/4ae1faea733b 随着企业的发展,他们的工作流程变得更加复杂,越来越多的有着错综复杂依赖关系的工作流需要增加监控,故障排除.如果没 ...

  2. hive中的with用法

    hive 可以通过with查询来提高查询性能,因为先通过with语法将数据查询到内存,然后后面其它查询可以直接使用,这种方法与创建临时表类似但是不需要创建临时表实体表,内存中的子查询结果在会话结束后会 ...

  3. ClassThree__HomeWork

    作业一 使用类的静态字段和构造函数,可以跟踪某个类所创建对象的个数.请写一个类,在任何时候都可以向它查询“你已经创建了多少个对象?”. 代码 public class TestOne {       ...

  4. linux 禁止22端口号

    重启防火墙命令#systemctl restart iptables.service 查看端口号#iptables -L首先修改配置文件 vi /etc/ssh/sshd_config 增加新端口号P ...

  5. Linux下java nohup 后台运行关闭后进程停止的原因,不挂断后台运行命令

    Linux下java nohup 后台运行关闭后进程停止的原因,不挂断后台运行命令 今天写sh脚本发现一终止命令程序就停止运行了,检查了很久才发现后面少了个&字符导致的!错误写法:nohup ...

  6. rabbitMq 教程

    https://github.com/401Studio/WeekLearn/issues/2 目录 RabbitMQ 概念 exchange交换机机制 什么是交换机 binding? Direct ...

  7. hud3007 Buried memory

    题目链接 最小圆覆盖 并不知道为什么是O(n)的,而且要随机化点的顺序 #include<algorithm> #include<iostream> #include<c ...

  8. javaweb笔记06—(页面跳转及编码格式)

    1.指令:<%@     %>:一个页面可以有多个import, 但是标识本页面为jsp页面的指令只能是一条(建议是一条 ) 2.出错页面:<%@ isError(true)%> ...

  9. 为了好好看球,学霸们用深度学习重建整个比赛3D全息图

    http://mp.ofweek.com/vr/a745673021206 周四晚上11点,万众瞩目的世界杯终于开踢了,虽然意大利.荷兰.智利.中国(手动滑稽)等强队没能进入本届世界杯,但C罗梅西谁主 ...

  10. django后台管理--添加自定义action

    管理员动作 简单来说,Django管理员的基本工作流程是“选择一个对象,然后进行更改”.这对大多数用例都很有效. 然而当你一次性要对多个对象做相同的改变,这个流程是非常的单调乏味的. 在这些情况下,D ...