JavaScript 运行机制 Event loop

2017-11-27  本文已影响0人  斯文的烟鬼去shi吧

JavaScript Event Loop

今天要分享的是javascript事件的运行机制,我们知道js是单线程的,但是为什么会是单线程?它又是怎么样运行的?

带梯子的直接传送help i'm stuck in an event-loop
这小哥讲得透彻 😂😂😂
想直接看结果可以翻到底部

历史原因

很早以前网上冲浪越来越流行时,对于开发客户端脚本的需求也逐渐增大。这时网页已经不断地变得更大和更复杂。而更加加剧用户痛苦的是,仅仅为了简单的表单有效性验证,就要与服务器进行多次地往返交互。设想一下,用户填完一个表单,点击提交按钮,等待了 30 秒的处理后,看到的却是一条告诉你忘记填写一个必要的字段。
急需开发一种客户端脚本语言来解决简单的处理问题。在客户端处理一部分事情,优化体验,同时也减轻了服务端的压力,当初的考虑只是一个脚本类型的辅助操作浏览器语言。
但是JavaScript是单线程呢?
不妨反过来想,如果js是多线程会怎么样?多个线程对同一个dom操作,这该怎么办?频繁的操作又该怎么办?浏览器的处理性能问题。所以JavaScript开发出来的原因就决定了是什么。


事件调用机制 call stack

接下来就是我们的重头戏js调用机制了,由于是单线程语言,这就意味着它只有一个单一的调用堆栈,也就是每次只能做一件事。
就拿比较流行的V8引擎来说,组成由:

JS运行的时候,会有栈内存(stack)和堆内存(heap),当我们用new实例化一个类的时候,这个new出来的对象就保存在heap里面,而这个对象的引用则存储在stack里。程序通过stack里的引用找到这个对象。例如var a = [1,2,3];,a是存储在stack里的引用,heap里存储着内容为[1,2,3]的Array对象。

在这里我们引出调用栈的概念
也就是你所写的JS代码是如何执行的,不多逼逼,看代码

function a() {
  console.log('a')
   //console.trace()
}

function b() {
  a()
}

function c() {
  b()
}

c()

这段简单的代码,相信都能看出来调用都顺序

嗯哼,很简单吧
how about

console.log('start')

setTimeout(function(){
  console.log('setTimeout')
}, 100)

sleep(100000000)

console.log('end')

这就要说到js异步处理了,为啥要用异步?同步(按照代码执行顺序)执行,setTimeout 100000000,空闲的cpu就要一直等待100000000ms,才继续执行任务,巨大的资源浪费明显是不合理的。so
在这里我就直接给出答案了,反正你们打开控制台也能直接看到了

//start
//end 
//setTimeout

那么

console.log('start')

setTimeout(function(){
  console.log('setTimeout 100')
}, 100)

setTimeout(function(){
  console.log('setTimeout 0')
}, 0)

console.log('end')

是0先输出呢还是100呢?
这样?

console.log('start')

setTimeout(function(){
  console.log('setTimeout 1')
  setTimeout(function(){
    console.log('setTimeout 3')
  }, 0)
}, 0)

setTimeout(function(){
  console.log('setTimeout 2')
}, 1000)

console.log('end')

异步在栈里面是如何调用的?
其实一个图就能看懂了

image.png
上一篇下一篇

猜你喜欢

热点阅读