• 好程序员web前端分享如何理解JS单线程,JS本质是单线程的。也就是说,它并不能像JAVA语言那样,两个线程并发执行。

    但我们平时看到的JS,分明是可以同时运作很多任务的,这又是怎么回事呢?

    首先,JS的代码,大致分为两类,同步代码和异步代码。

    console.log(1)

    console.log(2)

    console.log(3)

    这是典型的同步代码,编写顺序就是执行顺序。

    JS引擎的主线程负责执行代码,由于只有这一个线程,执行当然是同步的,即按照顺序来。另外,还有一个叫做任务队列的东西,所有的异步代码都是从队列当中来。

    所以实际上我们会发现,JS根本不可能同时执行两个任务,本质上还是单线程。

    在JS中,所谓的异步任务,有三种:

    第一,  鼠标键盘事件触发,例如onclick、onkeydown等等

    第二,  网络事件触发,例如onload、onerror等等

    第三,  定时器,例如setTimeout、setInterval

    因为这些任务的发生都不是在当下,而是过段时间以后再执行。因此时间不可控,你不能因为5秒后要执行一个函数,就让主线程闲置5秒什么都不干吧?所以你只能继续执行后续的同步代码。而当你单击鼠标或滚动窗口时,主线程可能正在执行其它代码,忙着呢!没工夫处理,因此,事件触发线程就负责来接收这个事件,并把要执行的任务暂时保存在任务队列当中。等主线程把手里的同步代码执行完,就立刻会向任务队列提取最新的任务。

    这也就解释了为什么我们总把JS的异步函数叫做回调了,因为真的不是马上执行,而是回头再调的!

    我们来看个简单的例子:

    setTimeout(“console.log(2)”, 0);
    console.log(1);

    反复执行这段代码,结果都是先打印1再打印2

    因为,setTimeout是个异步任务,第二个参数真正的含义是,在0毫秒之后,将代码插入任务队列,而不是在0毫秒之后执行。

    当插入任务队列后,主线程会继续执行后续的代码,也就是打印结果1,如果此时当前的同步代码已经执行完毕,则主线程立刻会从任务队列中取出最新任务执行。再打印结果2。

    平时我们使用定时器,时间往往不准确,就是因为在加入任务队列时,前面可能已经有好多任务在排队了,你明明写了80ms的延迟,可是却等了100ms才出现结果。

     

    同时,我们也理解了,为什么setInterval的时间间隔不能设为0,一般情况下浏览器允许的最小值为16ms,因为如果设成0的话,对于浏览器来讲,压力简直太大了,定时器触发线程会玩命儿的往队列中插入任务,而不是完成一个再插入一个。

    我们再看一个关于ajax的例子

    var req = newXMLHttpRequest();

    req.open(“get“, “http://xxxxxxxx“);

    req.onload =function(){......}

    req.send();

    我曾经在课堂跟学生讲课的时候,不小心把这个概念给讲错了,我当时说send方法和onload是不可以交换顺序的,实际上完全没有影响。被我误导的同学,我表示万分抱歉!希望此贴可以弥补我的罪过。

    为什么说send方法和onload交换顺序完全没有问题呢? 因为send是一个异步方法,也就是当我们把代码写成这样:

    var req = newXMLHttpRequest();

    req.open(“get“, “http://xxxxxxxx“);

    req.send();

    req.onload =function(){......}

    主线程在send方法执行时,由于是异步方法,因此它不会立刻执行,而是存入任务队列,然后继续向下执行代码,添加onload事件。所以send方法无论如何都会在添加onload事件之后再执行,因此顺序颠倒是无关要紧的。不过需要提醒的是,onload事件在添加时,并不会加入任务队列,而是通知网络事件触发线程,一旦网络请求结束,事件被触发,该线程便会立刻向任务队列中加入这个onload函数,从而完成回调。

    最后我们用一个完整的例子来观察一下JS如何以单线程执行代码

    setTimeout( a, 0);

    setInterval( b,500);

    for(......){

    //假设循环执行了大量操作,花费时间1000ms

    //而在for循环执行期间,用户通过鼠标触发了一次单击事件

    }

    console.log(123);

    setInterval(c,250);

    那么任务队列的情况如下:

    a

    b

    click

    b

    c

    c

    b

    c

    c

    b

    ...

    我们按顺序来解释一下:

    任务a,由于延迟为0,则以最短时间立即加入队列。

    任务b,等待500ms后,加入队列,此时for循环运行过半

    任务click,由于发生在for循环执行期间,所以此时出现

    任务b,for循环结束时,又过了500ms,因此加入b

    任务c,从for循环结束时开始计时,250ms后加入c

    任务c,因为又过了250ms

    任务b,与此同时,距离上次加入b间隔为500ms,因此加入b

    往后,每出现两次c,出现一次b

    OK!今天的课到此结束,同学们再见!  有问题请留言。

好程序员web前端分享如何理解JS的单线程的更多相关文章

  1. 好程序员web前端分享12个CSS高级技巧汇总

    好程序员web前端分享下面这些CSS高级技巧,一般人我可不告诉他哦. 使用 :not() 在菜单上应用/取消应用边框 给body添加行高 所有一切都垂直居中 逗号分隔的列表 使用负的 nth-chil ...

  2. 好程序员web前端分享值得参考的css理论:OOCSS、SMACSS与BEM

    好程序员web前端分享值得参考的css理论:OOCSS.SMACSS与BEM 最近在The Sass Way里看到了Modular CSS typography一文,发现文章在开头部分就提到了OOCS ...

  3. 好程序员web前端分享HTML基础篇

    好程序员web前端分享HTML基础篇,最近遇到很多新手,都会问,如果要学web前端开发,需要学什么?难不难学啊?多久能入门之类的问题?那么今天好程序员就先来给大家分享一下web前端学习路线:HTML基 ...

  4. 好程序员web前端分享想要学习前端需要学那些课程

    好程序员web前端分享想要学习前端需要学那些课程,仔细思考了一下如何回答好这个话题,其实前端是一个涵盖面非常之广泛的一个职位,所需知识体系非常庞杂,与传统语言“想要精一行,必先通一门” 有很大差别, ...

  5. 好程序员web前端分享javascript关联数组用法总结

    好程序员web前端分享javascript关联数组用法总结,有需要的朋友可以参考下. Hash关联数组定义 代码如下 // 定义空数组 myhash = { } // 直接定义数组 myhash = ...

  6. 好程序员web前端分享18个用CSS制作出来的东西

    好程序员web前端分享18个用CSS制作出来的东西,与流行的看法相反,CSS不仅仅是用来提供一个WEB页面的基本风格,以使它看起来更有吸引力.还有很多其他的事情,CSS也可以做的很好.由于它创建动画和 ...

  7. 好程序员web前端分享css常用属性缩写

    好程序员web前端分享css常用属性缩写,使用缩写可以帮助减少你CSS文件的大小,更加容易阅读.css缩写的主要规则如下: 颜色 16进制的色彩值,如果每两位的值相同,可以缩写一半,例如: #0000 ...

  8. 好程序员web前端分享CSS元素类型

    好程序员web前端分享CSS元素类型 目标 1.元素类型分类依据和元素类型分类 2.元素类型的转换 3.inline-block元素类型的应用 4.置换和非置换元素的概念和应用案例 一.元素类型分类依 ...

  9. 好程序员web前端分享前端学习路线自学如何找到工作

    好程序员web前端分享前端学习路线自学如何找到工作,自学能不能学会WEB前端并且找到WEB前端开发岗位的工作取决于自身条件,如果基础好,自律性强那么将会容易很多,还有就是自学最难克服的并不是知识点,而 ...

随机推荐

  1. Followme Devops实践之路

    引言 天下武功,唯快不破 想要提高开发团队效率,势必要有一套完整而成熟的开发流程方案,除了sprint迭代开发模式之外,还有近几年流行的devops流程,都是可以大幅度提高开发效率的工具. 我们团队也 ...

  2. 腾讯云服务器搭建Apache/PHP/MySQL环境

    软件环境 Windows Server 2008 R2 企业版 SP1 64位 刚刚进入 Windows Server ,你会看到以下界面: 列出了服务器的基础信息和常用配置 下载 XAMPP htt ...

  3. 【Android Studio安装部署系列】十四、Android studio移除工程和删除项目

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 概述 Android Studio删除工程.项目的操作步骤. 移除工程 主要用于从最近打开的项目列表中移除.硬盘中还是存在这个项目的. F ...

  4. 全文检索-Elasticsearch (三) DSL

    DSL:elasticsearch查询语言elasticsearch对json 的语法有严格的要求,每个json串不能换行,同时一个json串和一个json串之间,必须有一个换行 DSL(介绍查询语言 ...

  5. Python编程从入门到实践笔记——文件

    Python编程从入门到实践笔记——文件 #coding=gbk #Python编程从入门到实践笔记——文件 #10.1从文件中读取数据 #1.读取整个文件 file_name = 'pi_digit ...

  6. sublime text3插件解决输入法不跟随的问题

    快捷键ctrl + shift +p 输入  install package 回车,调出插件搜索器, 在搜索栏中输入 IMESupport 回车安装插件. 即可解决问题.

  7. 使用JsonProperty Attribute修改返回json

    使用JsonProperty Attribute修改返回 json 值的name 本例使用JsonPropertyAttribute在序列化为JSON时更改属性的名称. public class Vi ...

  8. tablednd onDrap 方法不调用

    场景 使用 tablednd 插件时,onDrap 方法不调用 解决 给tr标签加 id 属性

  9. odoo 12企业版与免费社区版的区别,价格策略与技术支持指南的全面解析

    Odoo / Ps Cloud收费企业版是对社区版的极大增强,除了增加了很多功能外,最大的功能区别是企业版支持条码而社区版不支持,企业版对手机支持更好.有单独的APP,最重要区别的是企业版提供底层技术 ...

  10. linux添加crontab定时任务

    1.crontab -e命令进入linux定时任务编辑界面,举个简单的例子,比如我要定时往txt文件写入 */ * * * * .txt */1就是每隔一分钟像文件写入,其他一些详细的操作大家可以去网 ...