JavaWeb|JavaScript(8)深入理解作用域

1,深入理解作用域 1.1什么是作用域 作用域指一个变量的作用的范围。通常来说,一段程序代码在所用到的名字并不总是有效和可用的,而限定于这个名字的可用性代码范围就是这个名字的作用域。作用域的使用提高了程序的逻辑的局部性,增强了程序的可靠性,减少了名字的冲突。
共有两种作用域类型:

  • 全局作用域
  • 函数作用域
1.1.1全局作用域
在script标签中的JavaScript代码都是全局作用域,当页面打开时全局作用域就会自动创建,而当页面关闭时,也会随之销毁。在全局作用域之中有一个全局的window对象可以使用,而所有全局作用域对象都会作为window对象属性来使用
1.1.2函数作用域
作用于函数内部的代码环境,就是局部作用域。局部作用域是在调用函数时被创建,函数执行完毕自动销毁。在函数作用域中可以访问全局作用域。而在全局作用域中不能访问函数作用域。挡在函数作用域中使用一个变量时,它会先到自身作用域内查找
1.1.3自动全局
如果为尚未声明的变量赋值,那么这个变量会自动变成全局变量。
如果在函数中定义变量时,没有指定关键字var,那么这个变量会自动提升为全局作用域变量。
1.2作用域的内部原理 编译阶段→执行阶段→查询阶段→嵌套阶段→异常阶段
  • 编译阶段,编译器把程序分解为词法单元,将词法单元解析为AST,再把AST转换为机器指令,等待执行的过程
  • 执行阶段:引擎运行代码时,首先查找当前作用域,看a变量是否在当前作用域下,如果是,引擎就会找到这个变量,否则会继续查找
  • 查询阶段:当变量在赋值操作的左侧时就叫LHS(左查询),出现在右侧就叫RHS右查询()
1.3词法作用域 是指当前作用域下所有生命的标识符
1.4遮蔽效应 作用域查找从运行时所处的最内部作用域开始,逐级向上进行查找,知道遇到第一个匹配的标识符为止。
在多层的嵌套作用域可以定义同名的标识符,这就叫做遮蔽效应。
1.5预解析 预解析是指在当前作用域下,JavaScript代码执行前,浏览器会把带var和function声明的变量在内存中进行提前声明或者定义。
1.5.1变量预解析
是指变量的声明会被提升到当前作用域的最上面,但变量的赋值不会提升
1.5.2函数预解析
指函数的声明会被提升到当前作用域的最上面,但不会调用函数。
1.5.3声明注意事项
  • 变量声明和函数声明时,变量的声明提升优于函数的声明提升,但是,函数的声明会覆盖未定义的同名变量。
1.5.4变量提升的原因
在编译阶段,引擎会声明变量和函数,但不会对变量进行赋值,这主要是出于对性能的考虑。变量被声明,但是不一定会在后面使用到,如果没有使用却赋了值,只是白白浪费内存而已。上面例子中的全局变量b,在函数fo没有执行之前,也不会赋值,直到函数中使用了这个变量,才不得不去加载数字1。简单的说,var a这段代码发生在编译阶段,而=1这段代码会根据实际情况,发生在执行阶段,这也就是"变量提升"的原因。另外需要注意的是,函数声明的是整个函数体(因为函数声明不存在赋值操作),而且优先级高于同名的变量。
1.6作用域链 各个作用域的嵌套关系组成一条作用域链。例子中 bar函数的作用域链式 bar -> fn>全局,fn 函数保存在作用域链式fn->全局
作用作用域链主要是进行标识符(变量和函数)的查询,标识符解析就是沿着作用域链一级一级的搜索标识符的过程,而作用域链就是保证对变量和函数的有序访问。
  • 如果自身作用域中声明变量,则无需作用域链
  • 如果自身作用域中未声明变量,则需要使用作用域链进行查找。
1.7自由变量 在当前作用域中存在但未在当前作用域中声明的变量叫自由变量。
在程序中如果存在自由变量,则一定存在作用域链。
1.8执行环境 执行环境(execution context)也叫上下文、执行上下文环境。每个执行环境都有一个与之关联的变量对象(variable object),环境中定义的所有变量和函数都保存在这个对象中。JavaScript代码执行的环境非常重要,而执行环境可以归纳为以下三种:
  • 全局代码(Global Code)-代码首次执行时的默认环境
  • 函数代码(Function Code)-程序执行到函数体内时
  • Eval函数代码(Eval Code) -内置Eval函数计算的字符串
1.9执行流程 JavaWeb|JavaScript(8)深入理解作用域
文章图片

1.10执行栈 【JavaWeb|JavaScript(8)深入理解作用域】当打开网页或浏览器时,宿主环境会将代码传递给引擎去执行,引擎首先会创建一个全局执行环境。全局环境中的代码自上而下有顺序的执行,当遇到一个函数时,函数的环境被创建,函数中的代码开始执行; 而在函数执行之后,控制权习返还给之前的环境。ES这种类似于"栈"的控制机制,称为执行栈。简单的说,执行环境栈就是一个压栈和出栈的过程。
  • 宿主环境:浏览器或者Node环境
  • 引擎:从头到尾负责整个JavaScript代码编译及执行过程
  • 栈:一种遵循“后进后出”原则的有序数据集合,可以简单理解为使用push()和pop()操作数组

    推荐阅读