深入理解JS|青训营笔记

37 阅读4分钟

JS生命周期

什么是执行上下文?

  • 在 JavaScript 中,执行上下文是一个抽象概念,用于描述代码在运行时的环境。

干什么用的?

  • 每当 JavaScript 代码执行时,都会创建一个执行上下文对象,该对象包含了执行该代码所需的所有信息,例如变量、函数、作用域、this 等。

执行上下文有哪些分类吗?

  • JavaScript 中有三种不同类型的执行上下文:
    1. 全局执行上下文(Global Execution Context):全局执行上下文是默认的、最外层的执行上下文,它在整个脚本执行期间都存在。全局执行上下文中定义的变量和函数可以被任何其他执行上下文访问。
    1. 函数执行上下文(Function Execution Context):每当一个函数被调用时,就会创建一个新的函数执行上下文。函数执行上下文包含了函数内部定义的所有变量、函数和参数,还包括一个指向函数外部的作用域链。
    1. 【补充】 Eval 执行上下文(Eval Execution Context):使用 eval() 函数时会创建一个新的执行上下文,即 eval 执行上下文。eval 执行上下文中的变量和函数可以被任何其他执行上下文访问。

JS中如何操作执行上下文的?

  • 在 JavaScript 中,执行上下文是一种栈结构,每当一个新的执行上下文被创建时,它都会被推到执行上下文栈的顶部。当代码执行完毕后,该执行上下文会从栈中弹出,控制权会返回到上一个执行上下文。

了解完执行上下文的相关内容后,来看看JS一些特殊或高级的用法

闭包

什么是闭包?

  • 闭包(Closure)是指一个函数能够访问在其定义时的词法作用域之外的变量。

怎么样的算闭包?

  • 当函数执行完毕后,它的词法作用域会被销毁,其中定义的变量和函数也会被销毁。但是,如果一个内部函数(嵌套函数)在外部函数执行完毕后仍然可以访问外部函数的变量和参数,那么这个内部函数就形成了一个闭包。

理解完后,来看看怎么用闭包

var createCounter = function(n) {
    let count = n - 1
    return function() {
        count += 1
        return count
    }
}

还记得我们前面提到的,在外部函数执行完毕后仍然可以访问外部函数的变量和参数。因此,在createCounter 函数中,function 依然可以访问外部函数的变量和参数 count

  • 闭包有个特点,可以保存内部函数的值,这就可以实现计数的功能,如上面的代码,我们就实现了一个计数,每次调用函数就在原基础上+1.

事件循环

  • JavaScript是一种单线程语言
  • JavaScript 有同步和异步的概念

比如说 setTimeout就是异步的 (最少执行时间是4ms,所以1,2,3,4是一样的)

浏览器是多线程的怎么办?

  • 这里就有一个误区需要理解,
  • JavaScript是单线程的指的是执行JavaScript代码的线程只有一个,是浏览器提供的JavaScript引擎线程(主线程)
  • 浏览器中还有定时器线程、 HTTP 请求线程等线程,这些线程主要不是来执行 JS 代码的

更多的JS单线程内容可以看看 == # 彻底搞懂JavaScript事件循环

微任务队列和宏任务队列

引擎的一般算法:

  1. 当有任务时:

    • 从最先进入的任务开始执行。
  2. 休眠直到出现任务,然后转到第 1 步

一般的执行步骤:设置任务 —— 引擎处理它们 —— 然后等待更多任务

一个任务到来时,引擎可能正处于繁忙状态,那么这个任务就会被排入队列。

多个任务组成了一个队列,即所谓的“宏任务队列”(v8 术语)

image.png

  • 微任务仅来自于我们的代码
  • 它们通常是由 promise 创建的
  • 微任务也被用于 await 的“幕后”,因为它是 promise 处理的另一种形式 微任务会在执行任何其他事件处理,或渲染,或执行任何其他宏任务之前完成

更多例子可以看看大佬是怎么解说的 == # 事件循环:微任务和宏任务