作用域
在解释这些专业术语之前,我说一下个人观点:我一直认为专业术语的概念往往不是绝对的,特别是当其应用在广泛的领域。
作用域就是如此,在计算机语言中经常被提起,所以本文对作用域的解释主要是作者比较赞同的观点。
来自wiki的释义:
In computer programming, the scope of a name binding—an association of a name to an entity, such as a variable—is the region of a computer program where the binding is valid: where the name can be used to refer to the entity.
简单来说:对于计算机编程,作用域就是一个变量可以被访问的范围。
The term "scope" is also used to refer to the set of all entities that are visible or names that are valid within a portion of the program or at a given point in a program, which is more correctly referred to as context or environment.
上面这句话我非常赞同:作用域也可以用来描述某一范围内变量的集合(例如在大多数计算机语言中,函数包含的所有局部变量,这些变量只能在函数内引用),这时候把作用域称为上下文或者环境更为准确。
那么如何确定作用域,或者说如何确定变量可以在程序的哪些阶段被访问?
Strictly speaking and in practice for most programming languages, "part of a program" refers to "portion of the source code (area of text)", and is known as lexical scope. In some languages, however, "part of a program" refers to "portion of run time (time period during execution)", and is known as dynamic scope.
总结大多数的编程语言的作用域判定:通过分析源代码来确定作用域的是词法作用域,在程序运行时确定作用域的是动态作用域。
词法作用域
JavaScript 是词法作用域:
var a = 0;
function f1() {
console.log(a);
}
function f2() {
var a = 1;
f1();
}
f2(); // 0
对于大多数人来说(比如我),没接触过作用域之前分析这段代码是这样的:执行 f2,f2 中声明了局部变量 a,执行 f1,打印 a,这时候应该打印了 f2 中的 a。
实际上,上面是动态作用域的思路:我们分析代码的过程就是程序执行的过程,所以 a 的作用域是在程序执行时确定的。
然鹅真相是这样的:a 是从书写位置往上层查找,即 f1 中无 a,往上一层(全局)查找,有 a。
动态作用域
bash 是词法作用域:
a=1
function f1 () {
echo $a;
}
function f2 () {
local a=2;
f1;
}
f2
可以直接 cv 到命令行,查看打印结果。
这时候就比较符合我们人思考的习惯:即执行 f1 时,a 是从执行处往上层查找,即 f1 中无 a,往上一层 f2 查找,有 a。