作用域是一套规则,用于确定在何处以及如何查找变量。
作用域有两种主要的工作模型。第一种是最为普遍的,被大多数编程语言所接受的词法作用域,也就是静态作用域,Javascript
正式基于这种作用域的。另一种叫做动态作用域,我们这里不作讨论。我们主要来看一下两者的区别。
词法作用域和动态作用域
- 词法作用域: 无论函数在哪里被调用,也无论它如何被调用,它的词法作用域都只由函数被声明时所处的位置决定,换句话说,函数的作用域是函数在书写时决定的。
- 动态作用域: 动态作用域并不关心函数是如何声明以及在何处声明,只关心它们从何处调用,换句话说,函数的作用域是在函数被调用时决定的。
看以下代码:
1 | var a = 1; |
假设 Javascript
采用词法作用域,我们看一下执行过程:
执行函数 foo
,在函数 foo
内部查找是否有局部变量 a
,如果没有,根据函数书写的位置,查找上面一层的代码,发现a=1
,所以结果为1;
假设Javascript
采用动态作用域,我们看一下执行过程:
执行函数foo
,在函数foo
内部查找是否有局部变量a
,如果没有,就从调用函数的作用域,也就是bar
内部查找变量a
,发现a=2
,所以结果为2;
根据我们前面的说明,Javascript
是基于词法作用域的,所以结果为1。
思考
《JavaScript权威指南》在讲到词法作用域时,举了如下例子
1 | var scope = "global scope"; |
1 | var scope = "global scope"; |
根据词法作用域的规则,不论何时何地执行函数f()
,返回的scope
值都是checkscope
内部局部变量scope
的值,也就是local scope
。