作用域&作用域链
作用域(Scope)
INFO
1.什么是作用域
- 作用域是在运行时代码中的某些特定部分中变量,函数和对象的可访问性。
- 作用域决定了代码区块中变量和其他资源的可见性。
- 作用域最大的用处就是隔离变量,不同作用域下同名变量不会有冲突。
INFO
2.全局作用域
- 在代码中任何地方都能访问到的对象拥有全局作用域。
- 最外层函数 和在最外层函数外面定义的变量拥有全局作用域。
- 所有末定义直接赋值的变量自动声明为拥有全局作用域。
- 所有 window 对象的属性拥有全局作用域。
INFO
3.块级作用域
- 块级作用域在如下情况被创建:
- a. 在一个函数内部
- b. 在一个代码块(由一对花括号包裹)内部
作用域链(scope chain)
- 多个作用域对象连续引用形成的链式结构。
- 使用:当在 Javascript 中使用一个变量的时候,首先 Javascript 引擎会尝试在当前作用域下去寻找该变量,如果没找到,再到它的上层作用域寻找,以此类推直到找到该变量或是已经到了全局作用域,如果在全局作用域里仍然找不到该变量,它就会直接报错。
- 存储:作用域链在 JS 内部中是以数组的形式存储的,数组的第一个索引对应的是函数本身的执行期上下文,也就是当前执行的代码所在环境的变量对象,下一个索引对应的空间存储的是该对象的外部执行环境,依次类推,一直到全局执行环境
作用域与执行上下文
JavaScript 的执行分为:解释和执行两个阶段
解释阶段:
- 词法分析
- 语法分析
- 作用域规则确定
执行阶段:
- 创建执行上下文
- 执行函数代码
- 垃圾回收
- JavaScript 解释阶段便会确定作用域规则,因此作用域在函数定义时就已经确定了,而不是在函数调用时确定,但是执行上下文是函数执行之前创建的。执行上下文最明显的就是 this 的指向是执行时确定的。而作用域访问的变量是编写代码的结构确定的。
- 作用域和执行上下文之间最大的区别是: 执行上下文在运行时确定,随时可能改变;作用域在定义时就确定,并且不会改变。
- 一个作用域下可能包含若干个上下文环境。有可能从来没有过上下文环境(函数从来就没有被调用过);有可能有过,现在函数被调用完毕后,上下文环境被销毁了;有可能同时存在一个或多个(闭包)。同一个作用域下,不同的调用会产生不同的执行上下文环境,继而产生不同的变量的值。
补
- 作用域最为重要的一点是安全。变量只能在特定的区域内才能被访问,外部环境不能访问内部环境的任何变量和函数,即可以向上搜索,但不可以向下搜索, 有了作用域我们就可以避免在程序其它位置意外对某个变量做出修改导致程序发生事故。
- 作用域能够减轻命名的压力。我们可以在不同的作用域内定义相同的变量名,并且这些变量名不会产生冲突。