JS的单线程问题

昨天电话面试,面试官在问了一个关于setTimeOut()的问题,给我一个场景,在setTimeOut(func2,0)函数前有一个执行了3秒的函数func1(),那么func2会立刻执行吗?(我的回答是不会,先执行完func1()再执行func2()),然后面试官又换一个,把func1()放在setTimeOut()后面,同样设置时间0ms,那么func2()里面的函数会立刻执行吗?(我的回答是会的,这里就答错了,答案是不一定,因为要看主线程内的命令是否已经执行完了)。归根结底,面试官想考察我的地方是js的单线程问题。下面是我查找资料后的一些总结。

一、Javascript是单线程的

单线程,即浏览器只分配给js一个主线程,用来执行任务,但一次只能执行一个任务,这些任务形成一个任务队列排队等候执行,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。

为什么JavaScript是单线程的,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?

为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完 全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。

虽然js是单线程的,但是浏览器内部是多线程的,除了js引擎线程,它还有UI渲染线程、浏览器事件触发线程、http请求线程……

 

二、同步和异步概念

前端的某些任务是非常耗时的,比如网络请求,定时器和事件监听,如果让他们和别的任务一样,都老老实实的排队等待执行的话,执行效率会非常的低,甚至导致页面无反应(假死)。

为了解决这个问题,Javascript语言将任务的执行模式分成两种:同步和异步。

"同步模式"就是在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;程序的执行顺序与任务的排列顺序是一致的、同步的;

"异步模式"则不进入主线程、而进入”任务队列”(也称消息队列),每一个任务指定回调函数,只要指定过回调函数,这些事件发生时就会进入”任务队列”,等待主线程读取。所谓”回调函数”,就是那些会被主线程挂起来的代码。

 

三、任务队列和事件循环

异步机制,这里要好好了解一下任务队列和事件循环。

请看下图(转引自Philip Roberts的演讲《Help, I’m stuck in an event-loop》)

 

Stack(栈)用来执行同步任务,即那种能立刻执行,不耗时的任务。Heap(堆)用来存储声明的变量、对象。上图中的虚线部分就是主线程,堆(heap)和栈(stack)共同组成了js主线程。下面的callback queue(回调队列也就是任务队列),当出现异步任务时,只要指定过回调函数,这些事件发生时就会进入"任务队列",等待主线程读取,执行对应的回调函数。

主线程的读取过程基本上是自动的,只要执行栈一清空,”任务队列”上第一位的事件就自动进入主线程。主线程从”任务队列”中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值