你不知道的——作用域

在执行javascript代码的过程中,主要由引擎、编译器、作用域处理我们的代码,首先来说说这几个成员的作用

  • 引擎
    从头到尾负责整个JavaScript程序的编译及执行过程
  • 编译器
    负责语法分析及代码生成
  • 作用域
    负责收集并维护由所有声明的标识符(变量)组成的一系列查询,确定当前执行的代码对这些标识符的访问权限

举个例子:
我要执行吃饭这个动作,此时的引擎就是 “我”,因为整个过程都是我在执行。吃饭就得有饭有菜,这些需要厨师给我做好放到我的饭桌上,此时 “厨师” 就扮演了编译器的角色。吃菜我只能吃我自己饭桌上的菜,所以我自己的饭桌就规定了我所能吃的菜,此时,“饭桌” 也就是一个作用域的体现

接下来:

    var a = 2

如上代码,引擎会认为我这里有两个完全不同的声明,一个由编译器在编译时处理,另一个则由引擎在运行时处理。

将其分解开来就是

	var a;
	a=2;

想想编译器会怎么做?

遇到 var a,编译器会询问作用域是否已经有一个该名称的变量存在于同一个作用域的集合中,如果是,编译器会忽略该声明,继续进行编译;否则它会要求作用域在当前作用域的集合中声明一个新的变量,并命名为 a

然后,编译器会为引擎生成运行时所需的代码,这些代码被用来处理 a=2 这个赋值操作。引擎运行时会首先询问作用域,在当前的作用域集合中是否存在一个叫作 a 的变量。如果是,引擎就会使用这个变量;如果否,引擎会继续查找该变量(作用域链查找)

如果引擎最终找到了 a 变量,就会将 2 赋值给它。否则引擎就会抛出一个异常!

再看!
1、

        console.log(b)

在这里插入图片描述
如上,在全局作用域中并没有 b 的声明,所以引擎会抛出 ReferenceError 错误,这种情况说明在所有的作用域中都没有找到 b 的声明

2、

        console.log(b)
        var b = 2

在这里插入图片描述
如上,var b=2,会存在变量提升,它实际执行顺序如下:

        var b
        console.log(b)
        b = 2

所以 b 会输出 undefined ,这种情况说明在 作用域中找到了 b 的声明,但是你尝试对这个变量的值进行不合理的操作,比如试图对一个非函数类型的值进行函数调用,或者引用 null 或 undefined 类型的值中的属性,那么引擎会抛出 TypeError 错误,如下所示:

        console.log(b.a)
        var b = 2

在这里插入图片描述

你可能感兴趣的:(前端面试,JavaScript,javascript)