JavaScript的运行机制
线程机制
进程与线程
进程(process):程序的一次执行, 它占有一片独有的内存空间,可以通过windows任务管理器查看进程
线程(thread):是进程内的一个独立执行单元,是程序执行的一个完整流程, 是CPU的最小的调度单元
应用程序必须运行在某个进程的某个线程上,一个进程中至少有一个运行的线程: 主线程, 进程启动后自动创建,一个进程中也可以同时运行多个线程, 我们会说程序是多线程运行的
一个进程内的数据可以供其中的多个线程直接共享,多个进程之间的数据是不能直接共享的
线程池(thread pool): 保存多个线程对象的容器, 实现线程对象的反复利用
何为多进程与多线程
多进程运行: 一应用程序可以同时启动多个实例运行
多线程: 在一个进程内, 同时有多个线程运行
比较单线程与多线程
多线程:优点:能有效提升CPU的利用率,创建多线程开销;缺点:线程间切换开销,死锁与状态同步问题
单线程:优点:顺序编程简单易懂;缺点:效率低
JS是单线程还是多线程
js是单线程运行的
但使用H5中的 Web Workers可以多线程运行
浏览器运行是单线程还是多线程
都是多线程运行的
浏览器运行是单进程还是多进程
有的是单进程:FireFox,老版本的IE
有的是多进程:chrome,新版本的IE
如何查看浏览器是否是多进程运行的呢
查看任务管理器-->进程
浏览器内核
支撑浏览器运行的最核心的程序
不同的浏览器可能不一样
Chrome, Safari : webkit
firefox : Gecko
IE : Trident
360,搜狗等国内浏览器: Trident + webkit
内核由很多模块组成
js引擎模块 : 负责js程序的编译与运行(主线程)
html,css文档解析模块 : 负责页面文本的解析(主线程)
DOM/CSS模块 : 负责dom/css在内存中的相关处理 (主线程)
布局和渲染模块 : 负责页面的布局和效果的绘制(内存中的对象)(主线程)
定时器模块 : 负责定时器的管理(分线程)
DOM事件响应模块 : 负责事件的管理(分线程)
网络请求模块 : 负责ajax请求(分线程)
JS代码块
JS中的代码块是指由<script>标签分割的代码段。JS是按照代码块来进行编译和执行的,代码块间相互独立(即就算代码块1出错,但不影响代码块2的加载和执行),但变量和方法共享。
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>无标题文档</title>
<script type="text/javascript">
console.log("这是代码块一");
var a = 100;
function show() {
console.log("show")
}
</script> <script type="text/javascript">
show();
console.log ("这是代码块二");
console.log(a)
</script>
</head>
<body> </body>
</html>
结果可以看到第一个代码块中的方法和变量可以在第二个代码块中访问,但是需要注意的是:需要先定义在使用,因为js是同步并且单线程的,从上往下执行
HTML页面中JS的加载原理
在加载HTML页面的时候,当浏览器遇到内嵌的JS代码时会停止处理页面,先执行JS代码,然后再继续解析和渲染页面。
同样的情况也发生在外链的JS文件中,浏览器必须先花时间下载外链文件中的代码,然后解析并执行它,在这个过程中,页面的渲染和用户互交完全被阻塞。
由于现代浏览器都允许并行下载JS文件,因此<script>标签在下载外部资源时不会阻塞其他的<script>标签。遗憾的是JS下载过程仍然会阻塞其他资源的下载。
JS语言的一大特点就是单线程,也就是说,同一个时间只能做一件事情。之所以是单线程,是因为与它的用途有关,作为浏览器脚本语言,JS的主要用途是与用户互动以及操作DOM。
这决定了它只能是单线程,否则会带来复杂的同步问题。
先来看一段代码然后再来详细的说明js的运行机制,下面的一段代码执行顺序是什么
console.log(1);
setTimeout(function () {
console.log(2);
}, 0);
console.log(3);
console.log(4);
测试得到的结果是1,3,4,2,至于为什么会这么执行,原因就是因为js是单线程的(同一时间只能做一件事情),js的任务队列,同步任务先执行,后执行异步任务(setTimeout就是一个异步任务)
js引擎执行代码的基本流程
先执行初始化代码: 包含一些特别的代码,比如:设置定时器,绑定监听,发送ajax请求。 后面在某个时刻才会执行回调代码
setTimeout(function () {
console.log('timeout 3') //
}, 3000) setTimeout(function () {
console.log('timeout 2') //
alert('2222') //
}, 2000) alert('提示...') // 1, 暂停当前主线程的执行,同时暂停计时,点击确定后恢复主线程执行和计时
console.log('alert之后') //
JS任务可以分为两种:一种是同步任务,另一种是异步任务。注意,只有主线程空了,才会去读取"任务队列",这就是JS的运行机制,这个过程会不断重复。
同步任务:在主线程上排队执行的任务,只有前一个任务执行完毕了,才会执行后一个任务。
异步任务:在主线程之外,还存在一个“任务列队”,异步任务就是不进入主线程,而是进入“任务列队”的任务,只有“任务列队”通知主线程,某个异步任务可以执行了并且同步任务执行完毕,该任务才会进入主线程执行。
"任务列队"是一个事件的列队,IO设备完成一项任务,就在"任务队列"中添加一个事件,表示相关的异步任务可以进入"执行栈"了。主线程读取"任务队列",就是读取里面有哪些事件。"任务队列"中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(如鼠标点击、页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入"任务队列",等待主线程读取。所谓"回调函数",就是那些会被主线程挂起的代码。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。"任务队列"是个先进先出的数据结构,排在前面的事件,优先被主线程读取。主线程的读取过程基本上是自动的,只要执行栈一清空,"任务队列"上第一位的事件就自动进入主线程。但是,由于存在后文提到的"定时器"功能,主线程首先检查一下执行时间,某些事件只有到了规定的时间,才能返回主线程。
"任务队列"还可以放置定时事件,即指定某些代码在多少时间之后执行。定时器功能主要由setTimeout()和setInterval()这两个函数来完成,
它们的内部运行机制完全一样,区别在于前者指定的代码是一次性执行,后者则为反复执行。以下主要讨论setTimeou()方法:
setTimeout()接受两个参数,第一个是回调函数,第二个是推迟执行的毫秒数
console.log(1)
setTimeout(function (){
console.log(2)
}, 1000);
console.log(3)
上面代码的执行结果是1=>3=>2,因为setTimeout()将第二行推迟到1000毫秒之后执行
如果将setTimeout()的第二个参数设为0,就表示当前代码执行完(执行栈清空)以后立即执行
console.log(1)
setTimeout(function (){
console.log(2)
}, 0);
console.log(3)
上面代码的执行结果是1=>3=>2,因为只有在执行完第二行以后,系统才会去执行"任务队列"中的回调函数。
总之,setTimeout(fn, 0)的含义是,指定某个任务在主线程最早的空闲时间执行,也就是说尽可能早的执行。它在"任务队列"的尾部添加一个事件,因此要等到同步任务和"任务队列"现有的事情都处理完,才会得到执行。
需要注意的是,setTimeout()只是将事件插入了"任务队列",必须等到当前代码(执行栈)执行完,主线程(js是单线程的也就是说只有一个主线程)才会去执行它指定的回调函数,要是当前代码耗时很长,有可能要等很久
所以并没有办法保证回调函数一定会在setTimeout()指定的时间执行。
//只打印A,B不会执行,因为while一直在执行,同步代码还没执行完,异步不会执行
console.log('A');
setTimeout(function () {
console.log('B');
}, 0);
while (1) { }
来看下这段程序,执行结果是打印了四次4,因为先执行主线程的循环,setTimeout属于异步任务,被挂起了,所以是for先执行完了再执行setTimeout
for (var i = 0; i < 4; i++) {
setTimeout(function () {
console.log(i); //打印四次4
}, 1000);
}
这段程序执行的结果是1,2,3,4,是因为变量i的作用域的关系
for (let i = 0; i < 4; i++) {
setTimeout(function () {
console.log(i); //1,2,3,4
}, 1000);
}
主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。
为了更好地理解Event Loop,请看下图
stack:所有的代码都是在此空间中执行的
所有代码分类
初始化执行代码(同步代码): 包含绑定dom事件监听, 设置定时器, 发送ajax请求的代码
回调执行代码(异步代码): 处理回调逻辑
js引擎执行代码的基本流程
初始化代码===>回调代码
模型的2个重要组成部分:
事件管理模块(WebApis),回调队列(callback queue)
模型的运转流程
执行初始化代码, 将事件回调函数交给对应模块管理
当事件发生时, 管理模块会将回调函数及其数据添加到回调列队中
只有当初始化代码执行完后(可能要一定时间), 才会遍历读取回调队列中的回调函数执行
function fn1() {
console.log('fn1()')
}
fn1() // document.getElementById('btn').onclick = function () {
console.log('处理点击事件') // 触发事件的时候才会执行
} setTimeout(function () {
console.log('到点了') //
}, 2000) function fn2() {
console.log('fn2()')
}
fn2() //
H5 Web Workers多线程
为了利用多核CPU的计算功能,HTML5提出了web worker标准,允许JS脚本创建多个线程,但是子线程完全受主线程控制,且不能操作DOM,所以这个新标准并没有改变JS单线程的本质。
JavaScript的运行机制的更多相关文章
- 简述JavaScript的运行机制
想要理解JavaScript的运行机制,需要分别深刻理解以下几个点: · JavaScript的单线程机制 · 任务队列(同步任务和异步任务) · 事件和回调函数 · 定时器 · Event Loop ...
- 浅谈javascript的运行机制
积累一下这几天学的,记录一下: 一.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程 ...
- 用一个小例子来谈谈javascript的运行机制
先上例子! <script type="text/javascript"> console.log('博'); setTimeout(function(){ conso ...
- [转]JavaScript线程运行机制
从开始接触js时,我们便知道js是单线程的.单线程,异步,同步,互调,阻塞等.在实际写js的时候,我们都会用到ajax,不管是原生的实现,还是借助jQuery等工具库实现,我们都知道,ajax可以实现 ...
- 浏览器UI多线程及JavaScript单线程运行机制的理解
在上一篇博客中,我对jQuery的队列(queue)机制和动画(animate)机制做了一个深入的解析,在animate的实现机制其核心是依靠queue来完成的,其中在jQuery的链式调用部分,之前 ...
- JavaScript的运行机制!!!很重要很重要!!!!!!请看大神操作!
https://juejin.im/post/59e85eebf265da430d571f89
- 深入理解JavaScript运行机制
深入理解JavaScript运行机制 前言 本文是写作在给团队新人培训之际,所以其实本文的受众是对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 ...
随机推荐
- JSP+Servlet+mysql简单示例【图文教程】
下载MYSQL:http://dev.mysql.com/downloads/ 下载安装版的 然后安装(安装步骤就不详细说了) 安装好之后,点击托盘图标,打开管理工具 创建一个数据库 数据库的名字 ...
- linux图形化客户端
很多服务器都用linux 但这些linux都是没有图形化界面的, 一般也不建议在服务器上装图形化界面 我们都知道,维护linux,大部分都是使用命令 那么,为什么不能开发一个应用程序, 把图形化操作转 ...
- 【图文详细教程】maven3安装配置+eclipse离线安装maven3插件《《唯一成功的教程~~~2018-01-09》》
环境搭建前提: 1.电脑上已经安装了1.7以及以上版本的JDK(因为我提供的maven版本是最新的3.3.9的,要求最低JDK1.7) 2.配置好了ecplise并且能正常启动 第一步:下载maven ...
- R语言实战(三)——模拟随机游走数据
一.模拟随机游走数据示例 x <- matrix(0,1000,1) for(i in 1:1000){ x[i+1] <- x[i]+rnorm(1) } plot(x,type=&qu ...
- soapUI工具使用方法、简介、接口测试
一.soapUI简介 SOAP: WebService通过Http协议发送请求和接收结果时,发送的请求内容和结果内容都采用XML格式封装,并增加了一些特定的HTTP消息头,以说明HTTP消息头的内容格 ...
- java_有秒计时的数字时钟
题目内容: 这一周的编程题是需要你在课程所给的时钟程序的基础上修改而成.但是我们并不直接给你时钟程序的代码,请根据视频自己输入时钟程序的Display和Clock类的代码,然后来做这个题目. 我们需要 ...
- 初学HTML-6
表单:专门用来收集用户信息 表单元素:在HTML中,标签/标记/元素都是指HTML中的标签. eg:<a>a标签/a标记/a元素 浏览器中所以得表单标签都有特殊的外观和默认的功能. 格式: ...
- Thymeleaf学习记录(1)--启动模板及建立Demo
Thymeleaf是什么? Thymeleaf是适用于Web和独立环境的现代服务器端Java模板引擎.相比于JSP,Thymeleaf更简洁,渲染性能更好,维护性更好,它可以XML/XHTML/HTM ...
- Manjaro使用笔记-使用中国源的方法
我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错!生成可用中国镜像站列表: sudo pacman-mirrors -i -c China -m rank 勾选弹窗里面的所有源刷新 ...
- Oracle 11g中修改被锁定的用户:scott
在安装完Oracle10g和创建完oracle数据库之后,想用数据库自带的用户scott登录,看看连接是否成功. 在cmd命令中,用“sqlplus scott/ tiger”登录时,老是提示如下信息 ...