前端知识点梳理

146 阅读2分钟

作用域

作用域就是定义变量作用的区域,它能确定代码对变量的访问权限。

设定作用域的目的是为了:

  1. 避免变量名称冲突
  2. 限定变量的生命周期

作用域可以分为动态作用域和静态作用域,静态作用域(静态作用域有时候也叫做词法作用域)。

  • 动态作用域是:在函数调用的时候,才可以确定函数的作用域。
  • 静态作用域是:在函数定义的时候,就可以确定函数的作用域。

 JS采用的就是静态作用域。
JS有三个作用域,全局作用域,函数作用域,和ES6新增的块级作用域。

执行上下文

在js执行的过程中,js引擎并不是一行一行的解析代码,而是一段一段的解析。所以在解析一段代码之前,会进行一个准备工作,在准备工作的这段时间内,会进行变量提升和函数提升。 这被划分为一段一段的代码,就叫做执行上下文。js引擎又创建了一个执行上下文栈来管理执行上下文。

执行上下文栈是如何管理执行上下文的呢?

当执行一个函数的时候,就会创建一个执行上下文,并且压入执行上下文栈。当函数执行完毕的时候,就会将函数的执行上下文从栈中弹出。所以按照这个流程,模拟下代码执行的流程:

当js执行代码的时候,最先遇到的是全局代码,所以先向执行上下文栈中压入一个全局执行上下文。只有当整个应用程序结束的时候,全局执行上下文才会被清空,所以栈底部永远有一个全局执行上下文。

      function fun3() {
        console.log("fun3");
      }

      function fun2() {
        fun3();
      }

      function fun1() {
        fun2();
      }

      fun1();
      
1.  全局执行上下文入栈
1.  fun1入栈
1.  fun2入栈
1.  fun3入栈
1.  fun3出栈
1.  fun2出栈
1.  fun3出栈
1.  全局上下文出栈

再来看一道题:

      var scope = "global scope";
      function checkscope() {
        var scope = "local scope";
        function f() {
          return scope;
        }
        return f();
      }
      checkscope();

      var scope = "global scope";
      function checkscope() {
        var scope = "local scope";
        function f() {
          return scope;
        }
        return f;
      }
      checkscope()();

由于js是采用静态作用域的原因,二者的输出都是local scope。但二者的区别,就是执行上下文栈的变化不一样。

      代码1:
      checkscope 入栈
      F 入栈
      F 出栈
      checkscope 出栈


      代码2:
      checkscope 入栈
      checkscope 出栈
      F 入栈
      F 出栈