Skip to content
New issue

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

js异步题目(浅析) #18

Open
itstrive opened this issue Aug 8, 2019 · 0 comments
Open

js异步题目(浅析) #18

itstrive opened this issue Aug 8, 2019 · 0 comments
Labels
article small article js About Js something question

Comments

@itstrive
Copy link
Owner

itstrive commented Aug 8, 2019

先看一个题目

function fn(n){
    fn(n);
}
fn(1);

这个题目的运行结果毫无疑问, 内存溢出, Maximum call stack size exceeded

如果稍微变一下呢?

function fn(n){
    setTimeout(()=>fn(n),0)
}
fn(1);

这个改变,会发生什么呢?这时候不会内存溢出了。


以上题目能解释明白的,应该很懂异步

简单说,js异步其实是宿主环境赋予给js的一种能力。采用 Event loop的形式去 callback queue(回调队列)取异步任务到 call stack中执行。

看以下图,这个需要理解了就ok了。

image

js是单线程的,浏览器为那些异步任务单独开辟了一些线程(比如http请求线程,浏览器定时触发器,浏览器事件触发线程),当然我们可以统称为 webAPIs。

因为异步的情况会很多,所以会放到一个叫 callback queue 队列里面(可以叫异步任务队列)。

堆(heap)和栈(stack)共同组成了js主线程,函数的执行就是通过进栈和出栈实现的。

比如图中有一个fn()函数,主线程把它推入栈中,在执行函数体时,发现还需要执行上面的那几个函数,所以又把这几个函数推入栈中,等到函数执行完,就让函数出栈。等到stack清空时,说明一个任务已经执行完了,这时就会从callback queue中寻找下一个人任务推入栈中(这个寻找的过程,叫做event loop,因为它总是循环的查找任务队列里是否还有任务)

  • 比如现在有这么一个程序:
setTimeout(fn1, 0)

请问fn1会不会立刻执行,答案是不一定。需要看下主线程内是否执行完毕了。如果有程序会先执行

比如:

setTimeout(function(){console.log(1);},0);
console.log(2);

会先输出2,然后1

  • 回到最开始题目

你知道为何加上定时器,就不会内存溢出了么?因为压根不在js主线程内,所以每次都是避开避开。

@itstrive itstrive added question article small article js About Js something labels Aug 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
article small article js About Js something question
Projects
None yet
Development

No branches or pull requests

1 participant