一起做前端老司机吧!(JavaScript编程篇)

235 阅读5分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

本文同时参与 「掘力星计划」           ,赢取创作大礼包,挑战创作激励金

JavaScript编程

前言

众所周知,目前主流的JavaScript环境都是以单线程执行JavaScript代码,为啥采用单线程呢?自己百度不客气,欸就是玩儿

src=http___img.mp.itc.cn_upload_20161020_2a4e25556abb4c2aa2840b6ae3576f7a.gif&refer=http___img.mp.itc.gif 本章呢,主要带大家看看

  • 同步模式与异步模式
  • 事件循环与消息队列 来上车,兄弟们 微信图片_20210924160139.gif·

怎么区别同步和异步模式呢?

用下面一个简单的例子给大家讲解一下:

  • 同步:和同事一起去吃饭,同事说他有任务要做,做完了才能去吃饭,你等他做完了,一起去吃饭这就是
  • 异步:和同事一起去吃饭,同事说他有任务要做,做完了才能去吃饭,你先去吃饭了,他做完了之后才去吃饭,互不干涉,这就是异步

同步模式(Synchronous)

同步模式就是代码中的任务依次执行,后一个代码需要等前一个代码执行完毕后在执行,执行顺序就是我们编程的时候的顺序。在单线程的情况下,我们大多数都会以同步执行(并非同时执行,而是排队执行

例子

让我们看看下面的代码,默想一下会怎么执行?

console.log('global begin')
function bar () {
    console.log('bar task')
}
function foo () {
    console.log('foo task')
}
foo()
console.log('global end')

ok,在我们执行这个代码的时候,首先,我们的调用栈Call statck中会被压入一个匿名调用,我们可以理解为我们全部的函数被放入一个匿名函数中进行执行

Call statckConsole
(anonymous)--

接着,我们就会逐行执行我们的代码,遇到第一个代码:console.log('global begin'),在执行完毕这行代码后,我们的控制台输出了对应的消息

Call statckConsole
(anonymous)--
console.log('global begin')global begin

执行完毕第一行代码后,我们的执行栈,会弹出console.log('global begin'),让我们的代码继续往下执行

Call statckConsole
(anonymous)--
console.log('global begin')global begin

接下来我们遇到了两个函数的声明,function barfunction foo但是函数、变量的声明不会产生调用,所以我们继续往下,执行foo

Call statckConsole
(anonymous)--
console.log('global begin')global begin
foofoo task

foo函数中调用了 bar函数

Call statckConsole
(anonymous)--
console.log('global begin')global begin
foofoo task
barbar task

打印完成之后,bar函数就被任务栈弹出

Call statckConsole
(anonymous)--
console.log('global begin')global begin
foofoo task
barbar task

弹出bar后,我们的foo函数也调用结束了,他也被弹出任务栈,最后打印global end,我们的调用栈就会被清空

Call statckConsole
(anonymous)--
console.log('global begin')global begin
foofoo task
barbar task
console.log('global end')global end

image.png

这就是简单的同步执行机制,但是有几个比较麻烦的问题,如果某一个执行出现了堵塞,就会出现堵死的情况,这就引入了新东西啦

异步模式

不会等待这个任务结束才开始下一个任务,开启过后就立即往后执行下一个任务,后续逻辑一般会通过回调函数的方式定义,异步模式对于JavaScript非常主要,如果没有这个模式及单线程的JavaScript就无法同事处理大量的耗时任务;那这里我们也引用一段代码,来描述一下异步执行的过程

console.log('begin')
setTimeout(() => {
    console.log('timer1')
},1800)
setTimeout(() => {
    console.log('timer2')
    setTimeout(() => {
        console.log('timer3')
    },1000)
},1000)
console.log('end')

首先,我们的调用栈Call statck中会被压入一个匿名调用

Call statckConsoleWeb ApisQueue
(anonymous)------
--------

然后我们先执行第一行的console

Call statckConsoleWeb ApisQueue
(anonymous)------
console.log('begin')begin----

接着就来到了第一个重头戏,setTimeout,因为这里是异步调用,所以我们需要关心内部的api调用都做了什么东西?其实内部的api也很简单,就是开启了1.8s的计时器

Call statckConsoleWeb ApisQueue
(anonymous)------
console.log('begin')begin----
setTimeout('console.log(timer1)')--1.8s timer1--

代码继续往下执行,压入新的栈

Call statckConsoleWeb ApisQueue
(anonymous)------
console.log('begin')begin----
setTimeout('console.log(timer1)')--1.8s timer1--
setTimeout('console.log(timer2)')--1s timer2--

最后遇到了console的调用

Call statckConsoleWeb ApisQueue
(anonymous)------
console.log('begin')begin----
setTimeout('console.log(timer1)')--1.8s timer1--
setTimeout('console.log(timer2)')--1s timer2--
console.log('end')end----

这里我们的调用栈就都被弹出了,就开始了Enven loop的执行

Call statckConsoleWeb ApisQueue
(anonymous)------
console.log('begin')begin----
setTimeout('console.log(timer1)')--1.8s timer1--
setTimeout('console.log(timer2)')--1s timer2--
console.log('end')end----
----1.8s timer1--
----1s timer2--

两个异步任务根据时间情况,我们先执行timer2的内容,会在任务栈中压入一个方法

Call statckConsoleWeb ApisQueue
(anonymous)------
console.log('begin')begin----
setTimeout('console.log(timer1)')--1.8s timer1--
setTimeout('console.log(timer2)')--1s timer2--
console.log('end')end----
----1.8s timer1--
----1s timer2--
1s timer2------

接着我们会发现timer2中还有一个setTime

Call statckConsoleWeb ApisQueue
(anonymous)------
console.log('begin')begin----
setTimeout('console.log(timer1)')--1.8s timer1--
setTimeout('console.log(timer2)')--1s timer2--
console.log('end')end----
----1.8s timer1--
----1s timer2--
1s timer2timer2timer3--

然后在执行 timer1

Call statckConsoleWeb ApisQueue
(anonymous)------
console.log('begin')begin----
setTimeout('console.log(timer1)')--1.8s timer1--
setTimeout('console.log(timer2)')--1s timer2--
console.log('end')end----
----1.8s timer1--
----1s timer2--
1s timer2timer2timer3--
1.8s timer1timer1----

再然后执行 timer3

Call statckConsoleWeb ApisQueue
(anonymous)------
console.log('begin')begin----
setTimeout('console.log(timer1)')--1.8s timer1--
setTimeout('console.log(timer2)')--1s timer2--
console.log('end')end----
----1.8s timer1--
----1s timer2--
1s timer2timer2timer3--
1.8s timer1timer1----
------timer3

然后就是运行啦

Call statckConsoleWeb ApisQueue
(anonymous)------
console.log('begin')begin----
setTimeout('console.log(timer1)')--1.8s timer1--
setTimeout('console.log(timer2)')--1s timer2--
console.log('end')end----
----1.8s timer1--
----1s timer2--
1s timer2timer2timer3--
1.8s timer1timer1----
------timer3
timer3timer3--timer3

image.png

大致就是这样啦,可能我说的比较绕,大家稍微理解理解哈

image.png