1.什么是作用域
几乎所有的编程语言的最基本的功能之一,就是能够储存变量当中的值,并且可以在之后对这些值进行访问或修改。但是变量往往存在哪里?换句话说程序如何找到它们?这些问题说明需要设计一套良好的规则来储存变量,并且之后可以方便的找到它们。这套规则就叫作用域。
2.理解作用域
对于一段代码
var a = 2;
完成这段赋值代码简单来说需要三方来完成分别是:
- 引擎:负责整个JavaScript代码的执行过程。
- 编译器:负责语法分析和代码生成。
- 作用域:负责收集并维护所有声明的变量,并实施一套非常严格的规则,确定当前执行的代码对这些变量的访问权限。
它们是如何工作的呢?
1.首先遇到var a
,编译器会询问作用域:当前作用域集合是否有同名的变量,如果有编译器则会忽略改声明,如果没有它会要作用域在当前作用域集合声明一个新的变量a
。
2.接下来编译器会为引擎生成运行时的代码,引擎运行时会首先询问作用域当前集合下是否有a
这个变量,如果有则会将2
赋值给当前变量,如果没有找到引擎会继续查询a
将2
赋值给它,如果最终没有找到它引擎就会抛出一个异常。
3.作用域嵌套
当一个块或者函数嵌套在另一个块或者函数中时,就发生了作用域嵌套,当引擎在当前作用域下无法找到某个变量时就会像外层继续查询直到找到为止。
举个栗子
function foo(a){
console.log(a + b);
}
var b = 2;
foo(3);
分析一下这段代码的执行过程
执行foo(3)
时编译器会在当前作用域创建a
变量,当遇到b
时编译器会询问作用域当前作用域集合是否存在b
呢?作用域会告诉编译器存在,这时编译器就会忽略b
继续往下执行,接下来就该引擎上场了,首先执行b
的赋值,然后执行小括号内容将3
赋值给a
,然后执行打印函数,这时引擎发现当前作用域下a
的值是3
但是当前作用域下b
没有声明,这时引擎就会继续向上一级作用域进行查询,找到了b
的值为2
最终输出结果5
。
将作用域想象成一个大的集合每个块或函数都有自己专属的作用域,它们之间相互嵌套最终组成了一个层层的链条,这就是作用域链,引擎对于变量的查找都是沿着这条链条逐级去查询。