We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
几道常见面试题来看 JavaScript 执行机制
JavaScript
根据 JavaScript 的运行环境,锁定它为单线程,任务需要排队执行,如果网站资源比较大,这样会导致浏览器加载会很慢,但实际上并没有,大家肯定立刻想到了同步和异步。
所谓的同步和异步也是在排队,只是排队的地方不同。
同步任务进入主线程排队,异步任务进入事件队列中排队
同步任务和异步任务进入到不同的队列中,也就是上面讲的在不同地方排队。
同步任务进入主线程,异步任务进入事件队列,主线程任务执行完毕,事件队列中有等待执行的任务进入主线程执行,直到事件队列中任务全部执行完毕。
console.log('a') setTimeout(function(){ console.log('b') }, 200) setTimeout(function(){ console.log('c') }, 0) console.log('d')
结果:a d c b
a d c b
从上到下,该进入主线程的进入主线程,该进入事件队列的进入事件队列。
那么主线程中存在 console.log('a') 和 console.log('d'),定时器 setTimeout 延迟一段时间执行,顾名思义异步任务进入事件队列中,等待主线程任务执行完毕,再进入主线程执行。
console.log('a')
console.log('d')
setTimeout
定时器的延迟时间为 0 并不是立刻执行,只是代表相比于其他定时器更早的进入主线程中执行。
0
for(var i = 0; i < 10; i++) { setTimeout(function() { console.log(i) }, 1000) }
结果:十个10
十个10
每次 for 循环遇到 setTimeout 将其放入事件队列中等待执行,直到全部循环结束,i 作为全局变量当循环结束后 i = 10 ,再来执行 setTimeout 时 i 的值已经为 10 , 结果为十个10。
for
i
i = 10
10
将 var 改为 let ,变量作用域不同,let 作用在当前循环中,所以进入事件队列的定时器每次的 i 不同,最后打印结果会是 0 1 2...9。
var
let
除了经常说的同步任务和异步任务之外,更可分为宏任务,微任务
主要宏任务:整段脚本script setTimeout setTimeout... 主要微任务:promise.then...
整段脚本script
promise.then
执行流程:
const p = new Promise(resolve => { console.log('a') resolve() console.log('b') }) p.then(() => { console.log('c') }) console.log('d')
结果:a b d c
a b d c
promise
a
b
d
c
setTimeout(function(){ console.log('setTimeout') }, 0) const p = new Promise(resolve => { console.log('a') resolve() console.log('b') }) p.then(() => { console.log('c') }) console.log('d')
结果:a b d c setTimeout
a b d c setTimeout
setTimeout(function(){ console.log('setTimeout') }, 0) const p = new Promise(resolve => { console.log('a') resolve() console.log('b') }) p.then(() => { console.log('c') setTimeout(function(){ console.log('then中的setTimeout') }, 0) }) console.log('d')
结果:a b d c setTimeout then中的setTimeout
a b d c setTimeout then中的setTimeout
then中的setTimeout
console.log('a'); new Promise(resolve => { console.log('b') resolve() }).then(() => { console.log('c') setTimeout(() => { console.log('d') }, 0) }) setTimeout(() => { console.log('e') new Promise(resolve => { console.log('f') resolve() }).then(() => { console.log('g') }) }, 100) setTimeout(() => { console.log('h') new Promise(resolve => { resolve() }).then(() => { console.log('i') }) console.log('j') }, 0)
结果:a b c h j i d e f g
a b c h j i d e f g
h j
e f
g
console.log('start') a().then(() => { console.log('a_then') }) console.log('end') function a() { console.log('a_function') return b().then((res) => { console.log('res', res) console.log('b_then') return Promise.resolve('a方法的返回值') }) } function b() { console.log('b_function') return Promise.resolve('返回值') }
结果:start a_function b_function end res 返回值 b_then a_then
start
a_function
b_function
end
res 返回值
b_then
a_then
根据上面例子的流程讲解来思考这个,加深理解
The text was updated successfully, but these errors were encountered:
No branches or pull requests
前面的话
根据
JavaScript
的运行环境,锁定它为单线程,任务需要排队执行,如果网站资源比较大,这样会导致浏览器加载会很慢,但实际上并没有,大家肯定立刻想到了同步和异步。所谓的同步和异步也是在排队,只是排队的地方不同。
同步和异步
同步任务和异步任务进入到不同的队列中,也就是上面讲的在不同地方排队。
同步任务进入主线程,异步任务进入事件队列,主线程任务执行完毕,事件队列中有等待执行的任务进入主线程执行,直到事件队列中任务全部执行完毕。
开胃菜
结果:
a d c b
从上到下,该进入主线程的进入主线程,该进入事件队列的进入事件队列。
那么主线程中存在
console.log('a')
和console.log('d')
,定时器setTimeout
延迟一段时间执行,顾名思义异步任务进入事件队列中,等待主线程任务执行完毕,再进入主线程执行。定时器的延迟时间为
0
并不是立刻执行,只是代表相比于其他定时器更早的进入主线程中执行。加一盘
结果:
十个10
每次
for
循环遇到setTimeout
将其放入事件队列中等待执行,直到全部循环结束,i
作为全局变量当循环结束后i = 10
,再来执行setTimeout
时i
的值已经为10
, 结果为十个10。将
var
改为let
,变量作用域不同,let
作用在当前循环中,所以进入事件队列的定时器每次的i
不同,最后打印结果会是 0 1 2...9。宏任务 微任务
主要宏任务:
整段脚本script
setTimeout
setTimeout
...主要微任务:
promise.then
...执行流程:
来一盘Promise
结果:
a b d c
promise
创建立即执行,打印a
b
,promise.then
进入微任务队列,console.log('d')
打印d
,c
。结果:
a b d c setTimeout
setTimeout
进入宏任务队列,promise
创建立即执行,打印a
b
,promise.then
进入微任务队列,console.log('d')
打印d
,c
,setTimeout
开始执行,打印setTimeout
结果:
a b d c setTimeout then中的setTimeout
c
,遇到setTimeout
将其推入宏任务队列中setTimeout
then中的setTimeout
再加点定时器
结果:
a b c h j i d e f g
a
promise
立即执行,打印b
promise.then
推入微任务队列setTimeout
推入宏任务队列c
,遇到setTimeout
推入宏任务队列排队等待执行h j
,promise.then
推入微任务队列i
,继续执行宏任务,打印d
e f
,执行微任务打印g
,所有任务执行完毕简单测试
结果:
start
a_function
b_function
end
res 返回值
b_then
a_then
根据上面例子的流程讲解来思考这个,加深理解
总结
JavaScript
单线程,任务需要排队执行0
并不是立刻执行,只是代表相比于其他定时器更早的被执行The text was updated successfully, but these errors were encountered: