博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JS的运行机制
阅读量:6761 次
发布时间:2019-06-26

本文共 2028 字,大约阅读时间需要 6 分钟。

代码块: JS中的代码块是指由<script>标签分割的代码段。JS是按照代码块来进行编译和执行的,代码块间相互独立(即就算代码块1出错,但不影响代码块2的加载和执行),但变量和方法共享。
案例:2个代码块
 
 
  1. <script type="text/javascript"
  2.     console.log("这是代码块一"); 
  3. </script> 
  4.   
  5. <script type="text/javascript"
  6.     console.log ("这是代码块二"); 
  7. </script> 
  8.   
 
HTML页面中JS的加载原理: 在加载HTML页面的时候,当浏览器遇到内嵌的JS代码时会停止处理页面,先执行JS代码,然后再继续解析和渲染页面。同样的情况也发生在外链的JS文件中,浏览器必须先花时间下载外链文件中的代码,然后解析并执行它,在这个过程中,页面的渲染和用户互交完全被阻塞。由于现代浏览器都允许并行下载JS文件,因此<script>标签在下载外部资源时不会阻塞其他的<script>标签。遗憾的是JS下载过程仍然会阻塞其他资源的下载。
 
JavaScript的单线程:
JS语言的一大特点就是单线程,也就是说,同一个时间只能做一件事情。之所以是单线程,是因为与它的用途有关,作为浏览器脚本语言,JS的主要用途是与用户互动以及操作DOM。这决定了它只能是单线程,否则会带来复杂的同步问题。为了利用多核CPU的计算功能,HTML5提出了web worker标准,允许JS脚本创建多个线程,但是子线程完全受主线程控制,且不能操作DOM,所以这个新标准并没有改变JS单线程的本质。
 
JavaScript的任务列队:
JS任务可以分为两种:一种是同步任务,另一种是异步任务。注意,只有主线程空了,才会去读取"任务队列",这就是JS的运行机制,这个过程会不断重复。
同步任务:在主线程上排队执行的任务,只有前一个任务执行完毕了,才会执行后一个任务。
异步任务:在主线程之外,还存在一个“任务列队”,异步任务就是不进入主线程,而是进入“任务列队”的任务,只有“任务列队”通知主线程,某个异步任务可以执行了并且同步任务执行完毕,该任务才会进入主线程执行。
 
Javascript的事件和回调函数:
"任务列队"是一个事件的列队,IO设备完成一项任务,就在"任务队列"中添加一个事件,表示相关的异步任务可以进入"执行栈"了。主线程读取"任务队列",就是读取里面有哪些事件。"任务队列"中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(如鼠标点击、页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入"任务队列",等待主线程读取。所谓"回调函数",就是那些会被主线程挂起的代码。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。"任务队列"是个先进先出的数据结构,排在前面的事件,优先被主线程读取。主线程的读取过程基本上是自动的,只要执行栈一清空,"任务队列"上第一位的事件就自动进入主线程。但是,由于存在后文提到的"定时器"功能,主线程首先检查一下执行时间,某些事件只有到了规定的时间,才能返回主线程。
 
定时器:
除了放置异步任务的事件,"任务队列"还可以放置定时事件,即指定某些代码在多少时间之后执行。定时器功能主要由setTimeout()和setInterval()这两个函数来完成,它们的内部运行机制完全一样,区别在于前者指定的代码是一次性执行,后者则为反复执行。以下主要讨论setTimeou()方法:
setTimeout()接受两个参数,第一个是回调函数,第二个是推迟执行的毫秒数     
 
 
  1. console.log(1) 
  2. setTimeout(function (){ 
  3.      console.log(2) 
  4. }, 1000); 
  5. console.log(3) 
上面代码的执行结果是1=>3=>2,因为setTimeout()将第二行推迟到1000毫秒之后执行
 
如果将setTimeout()的第二个参数设为0,就表示当前代码执行完(执行栈清空)以后立即执行
 
 
  1. setTimeout(function (){ 
  2.      console.log(2) 
  3. }, 0); 
  4. console.log(3) 
上面代码的执行结果是3=>2,因为只有在执行完第二行以后,系统才会去执行"任务队列"中的回调函数。总之,setTimeout(fn, 0)的含义是,指定某个任务在主线程最早的空闲时间执行,也就是说尽可能早的执行。它在"任务队列"的尾部添加一个事件,因此要等到同步任务和"任务队列"现有的事情都处理完,才会得到执行。
 
需要注意的是,setTimeout()知识将事件插入了"任务队列",必须等到当前代码(执行栈)执行完,主线程才会去执行它指定的回调函数,要是当前代码耗时很长,有可能要等很久,所以并没有办法保证回调函数一定会在setTimeout()指定的时间执行。
来源:51CTO

转载地址:http://ipdeo.baihongyu.com/

你可能感兴趣的文章
DragonFly BSD 3.2 发布
查看>>
C#中为什么需要装箱拆箱操作?
查看>>
PHP类中一般方法与静态方法的疑问
查看>>
[转]PHP花括号变量
查看>>
Fedora16安装中文语言包和中文输入法
查看>>
Windows 8实用窍门系列:14.windows 8中粘贴板(剪切板)的使用
查看>>
ASP.NET中 RadioButtonList(单选按钮组)的使用
查看>>
SESSION 丢失
查看>>
DES可逆加解密
查看>>
如何理解ip路由和操作linux的路由表
查看>>
WCF的几种寄宿方式 ( 转)
查看>>
ORACLE 数据库 SQL 转换 只取 年和月
查看>>
区间查询[2009国家集训队]小Z的袜子(hose)
查看>>
Android之使用微信开放api (三)---注册与反注册应用到微信
查看>>
我是怎样看待微博的
查看>>
论《我是如何安慰女友的》
查看>>
Mono for Android安装配置破解
查看>>
WPF----数据绑定
查看>>
子类化GetOpenFileName/GetSaveFileName, 以及钩子函数OFNHookProc的使用的简要说明
查看>>
C语言中判断int,long型等变量是否赋值的方法
查看>>