JavaScript作用域与作用域链
2017-08-06 本文已影响0人
liushaung
作用域
什么是作用域?
- 作用域(execution context)定义了变量和函数有权访问的其他数据,决定了它们各自的行为。
- 每个作用域都有一个与之关联的活动对象,环境中所有的变量和函数都保存在这个对象中。我们无权访问这个对象,但解析器在处理数据时会在后台使用它。
全局作用域
- 全局作用域是最外围的作用域。
- 在浏览器中,全局作用域被认为是window对象,因此所有的全局变量和函数都是作为window对象的属性和方法创建的。
作用域的特性
- 某个作用域中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之被销毁。(全局变量关闭窗口或浏览器时才会被销毁)
每个函数都有自己的作用域
- 当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行之后,栈将其环境弹出,把控制权返回给之前的作用域。
作用域链
概念
- 作用域链本质上是一个指向活动对象的指针列表。
- 作用域链是由一级一级的活动对象组成的。
- 当代码在一个环境中执行时,会创建活动对象组成的一个作用域链。
- 作用域链的用途是保证对作用域有权访问的所有变量和函数的有序访问。
- 作用域链的前端,始终都是当前执行的代码所在环境的活动对象。
- 活动对象在最开始时只包含一个变量,即arguments对象,作用域中的下一个活动对象来自当前环境的包含环境,而再下一个活动对象则来自下一个包含环境,这样一直延续到全局环境;
- 全局环境的活动对象始终是作用域链中的最后一个对象。
- 内部环境可以通过作用域链访问所有的外部(包含)环境。
标识符解析
- 标识符解析是沿着作用域链一级一级地搜索标识符的过程。
- 搜索过程从作用域链的前端开始,然后逐级向上,直到找到标识符为止(如果没找到则会发生错误)。
- 每个作用域都只能向上搜索作用域链。
- 函数参数也被当作变量对待,因此它的访问规则与作用域中其他变量相同。
延长作用域链
- 有些语句可以在作用域链的前端临时增加一个活动对象,该活动对象会在代码执行后被移出。
- try-catch语句的catch块
- with语句
- 这两个语句都会在作用域链的前端临时添加一个活动对象。对with语句来说,会将指定的对象添加到作用域链中。对catch语句来说,会创建一个新的活动对象,包含被抛出的错误对象声明。
js没有块级作用域,只有局部作用域(函数作用域)和全局作用域
- 在JavaScript中,如果我们需要实现块级作用域,我们也有一种变通的方式,那就是通过自执行函数创建临时作用域。
- 对JavaScript解释器而言,所有的函数和变量声明都会被提升到最前面, 并且变量声明永远在前面,赋值会在执行到赋值语句后执行。
- 函数声明会自动将声明放在前面并且执行赋值过程。而函数表达式则是先将声明提升,然后到赋值处再执行赋值。
- 在一个作用域中:变量声明提升、函数声明复制并提升 =》 然后顺序执行。
- 带有命名的函数表达式,是不会进行声明提升的