JavaScript运行机制详解
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中的任务。
JavaScript运行机制详解的更多相关文章
- JavaScript 运行机制详解:再谈Event Loop
原文地址:http://www.ruanyifeng.com/blog/2014/10/event-loop.html 一年前,我写了一篇<什么是 Event Loop?>,谈了我对Eve ...
- JavaScript 运行机制详解:深入理解Event Loop
Philip Roberts的演讲<Help, I'm stuck in an event-loop>,详细.完整.正确地描述JavaScript引擎的内部运行机制. 一.为什么JavaS ...
- javascript运行机制详解: 再谈Event Loop(转)
作者: 阮一峰 日期: 2014年10月 8日 一年前,我写了一篇<什么是 Event Loop?>,谈了我对Event Loop的理解. 上个月,我偶然看到了Philip Roberts ...
- JavaScript 运行机制详解:Event Loop
参考地址:http://www.ruanyifeng.com/blog/2014/10/event-loop.html 一.为什么JavaScript是单线程? JavaScript语言的一大特点就是 ...
- JavaScript 运行机制详解
一.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊. Java ...
- 【repost】JavaScript 运行机制详解:再谈Event Loop
一年前,我写了一篇<什么是 Event Loop?>,谈了我对Event Loop的理解. 上个月,我偶然看到了Philip Roberts的演讲<Help, I'm stuck i ...
- [转] JavaScript 运行机制详解:再谈Event Loop
一.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊. Java ...
- [转载]JavaScript 运行机制详解:再谈Event Loop
https://app.yinxiang.com/shard/s8/sh/b72fe246-a89d-434b-85f0-a36420849b84/59bad790bdcf6b0a66b8b93d5e ...
- 【朴灵评注】JavaScript 运行机制详解:再谈Event Loop
PS: 我先旁观下大师们的讨论,得多看书了~ 别人说的:“看了一下不觉得评注对到哪里去,只有吹毛求疵之感. 比如同步异步介绍,本来就无大错:比如node图里面的OS operation,推敲一下就 ...
随机推荐
- 开源数据流管道-Luigi vs Azkaban vs Oozie vs Airflow
原文链接:https://www.jianshu.com/p/4ae1faea733b 随着企业的发展,他们的工作流程变得更加复杂,越来越多的有着错综复杂依赖关系的工作流需要增加监控,故障排除.如果没 ...
- hive中的with用法
hive 可以通过with查询来提高查询性能,因为先通过with语法将数据查询到内存,然后后面其它查询可以直接使用,这种方法与创建临时表类似但是不需要创建临时表实体表,内存中的子查询结果在会话结束后会 ...
- ClassThree__HomeWork
作业一 使用类的静态字段和构造函数,可以跟踪某个类所创建对象的个数.请写一个类,在任何时候都可以向它查询“你已经创建了多少个对象?”. 代码 public class TestOne { ...
- linux 禁止22端口号
重启防火墙命令#systemctl restart iptables.service 查看端口号#iptables -L首先修改配置文件 vi /etc/ssh/sshd_config 增加新端口号P ...
- Linux下java nohup 后台运行关闭后进程停止的原因,不挂断后台运行命令
Linux下java nohup 后台运行关闭后进程停止的原因,不挂断后台运行命令 今天写sh脚本发现一终止命令程序就停止运行了,检查了很久才发现后面少了个&字符导致的!错误写法:nohup ...
- rabbitMq 教程
https://github.com/401Studio/WeekLearn/issues/2 目录 RabbitMQ 概念 exchange交换机机制 什么是交换机 binding? Direct ...
- hud3007 Buried memory
题目链接 最小圆覆盖 并不知道为什么是O(n)的,而且要随机化点的顺序 #include<algorithm> #include<iostream> #include<c ...
- javaweb笔记06—(页面跳转及编码格式)
1.指令:<%@ %>:一个页面可以有多个import, 但是标识本页面为jsp页面的指令只能是一条(建议是一条 ) 2.出错页面:<%@ isError(true)%> ...
- 为了好好看球,学霸们用深度学习重建整个比赛3D全息图
http://mp.ofweek.com/vr/a745673021206 周四晚上11点,万众瞩目的世界杯终于开踢了,虽然意大利.荷兰.智利.中国(手动滑稽)等强队没能进入本届世界杯,但C罗梅西谁主 ...
- django后台管理--添加自定义action
管理员动作 简单来说,Django管理员的基本工作流程是“选择一个对象,然后进行更改”.这对大多数用例都很有效. 然而当你一次性要对多个对象做相同的改变,这个流程是非常的单调乏味的. 在这些情况下,D ...