前端面试-基础-JS(3)- 执行上下文

107 阅读2分钟

面试系列原地址 gitee.com/gusiil/fein…,持续更新中

执行上下文

执行上下文,即代码的执行环境,执行上下文有三个重要的属性

  • 变量对象
  • 作用域链
  • this

有两个重要的阶段:

  1. 进入执行上下文
  2. 代码执行

属性

变量对象

  • 全局对象
  • 函数对象

变量提升和函数提升:
在进入执行上下文时候,还没执行代码时,会进行以下三个声明步骤

  1. 形参声明
  2. 函数声明
    • 函数声明会提到最前
    • 如果变量对象已存在,则替换
  3. 变量声明
    • 如果变量名称跟一家声明的形参或者函数相同,则不会干扰
    • var a = function(){} 此类函数的字面量声明是变量声明,声明阶段
console.log(a()); // 1

var a = 2

function a() {
    return 1
}

console.log(a); // 2

以上代码块,无论var a = 2 function a 如何交换位置,输出值不变

TDZ 暂时性死区:为了避免这些反人类的感官,ES6 提供了 letconst声明方式
let/const 会令区块形成封闭的作用域,若在声明之前使用变量,就会报错

作用域链

多个执行上下文的变量对象构成的链表,能冲下往上的查找变量

this

点击此处

执行上下文栈

在我们写代码中,不止有一个函数,也就是说会有多个执行上下文的创建和执行
为了统一管理执行上下文,js 引擎创建了一个执行上下文栈来统一管理各个上下文

  1. js 执行,压入全局执行上下文。这个全局上下文只有在应用程序结束或者页面关闭的时候,才会被弹出
  2. 当一个感受被调用啥时,创建执行上下文并压入。当函数执行结束,弹出

闭包

MDN 解释如下:

闭包是指那些能访问自由变量的函数

自由变量是指:

自由变量是指那些能在函数中使用,但既不是函数参数也不是函数局部变量的变量,及不属于函数执行上下文的变量

即,闭包等价于函数 + 函数能访问的自由变量
从技术角度说,闭包等价于函数

var data = [];

for (var i = 0; i < 3; i++) {
  data[i] = () => console.log(i);
}

data[0](); // 2
data[1](); // 2
data[2](); // 2

data[i] 函数访问的 i 是 for 循环内部的 i,因此永远返回 3
我们在创建一个执行上下文,将每个 i 保存下来

var data = [];

for (var i = 0; i < 3; i++) {
  data[i] = ((i) => () => console.log(i))(i)
}

data[0](); // 0
data[1](); // 1
data[2](); // 2

es6 中的 let 和 const 会形成块级作用域,因此也可以解决该问题