作用域是一套规则,用于确定在何处以及如何查找变量。
作用域有两种主要的工作模型。第一种是最为普遍的,被大多数编程语言所接受的词法作用域,也就是静态作用域,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。