工作做完的闲暇之余逛了segmentfault,发现了一篇有意思的文章——JavaScript 运行机制—q,发现自己对javascript的闭包以及运行机制并不了解,特查资料,整理。
|
|
F2函数就是闭包,闭包就是能够读取其他函数内部变量的函数,是把函数内部和外部连接的桥梁。
闭包的作用有两个:一是可以读取函数内部的变量,二是让这些变量的值始终存在内存中。
|
|
这段代码中,rusult实际上就是闭包函数f2,他一共运行了两次,第一次为999,第二次为1000,这证明了函数f1的局部变量n一直保存在内存中,并没有在f1调用之后被自动清除。原因是,f1是f2的父函数,而f2赋值给了一个全局变量,导致f2始终在内存中,而f2始终依赖于f1,因此f1也始终在内存中,不会在调用后被垃圾回收机制回收。
闭包的大概内容就到此为止,下面,我们来学习一下js的运行机制。
js的一大特点就是单线程,也就是同一时间只能做一件事。单线程就意味着所有任务需要排队,前一个任务结束才会进行下一个任务。当任务需要IO设备时,(比如等着ajax操作获取数据)虽然CPU是空闲状态,但不得不等着结果返回才能进行下一个任务。这时,主线程完全可以不管IO设备,挂起等待中的任务,先运行排在后面的任务,等IO设备返回了结果,再把挂起的任务继续执行。
因此,所有任务可以分为两种,一种同步任务,一种异步任务。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行结束,才能执行后一个任务。异步任务指的是,不进入主线程,而进入“任务队列”的任务,只有“任务队列”通知主线程,该任务可以执行,才进入主线程。
- 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
- 主线程之外,还存在一个”任务队列”(task queue)。只要异步任务有了运行结果,就在”任务队列”之中放置一个事件。
- 一旦”执行栈”中的所有同步任务执行完毕,系统就会读取”任务队列”,看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
- 主线程不断重复上面的第三步。
“任务队列”中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入”任务队列”,等待主线程读取。
所谓”回调函数”(callback),就是那些会被主线程挂起来的代码。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。
主线程从”任务队列”中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。
除了放置异步任务的事件,”任务队列”还可以放置定时事件,即指定某些代码在多少时间之后执行。