Page 156 - Node.js开发指南
P. 156
附录 A JavaScript 的高级特性 149
作用域是通过函数来定义的,在一个函数中定义的变量只对这个函数内部可见,我们称为函 1
数作用域。在函数中引用一个变量时,JavaScript 会先搜索当前函数作用域,或者称为“局
部作用域”,如果没有找到则搜索其上层作用域,一直到全局作用域。我们看一个简单的
例子:
2
var v1 = 'v1';
var f1 = function() {
console.log(v1); // 输出 v1
}; 3
f1();
var f2 = function() {
var v1 = 'local';
console.log(v1); // 输出 local
}; 4
f2();
以上示例十分明了,JavaScript 的函数定义是可以嵌套的,每一层是一个作用域,变量
搜索顺序是从内到外。下面这个例子可能就有些令人困惑:
5
var scope = 'global';
var f = function() {
console.log(scope); // 输出 undefined
var scope = 'f'; 6
}
f();
上面代码可能和你预想的不一样,没有输出 global,而是undefined,这是为什么呢?
这是 JavaScript 的一个特性,按照作用域搜索顺序,在 console.log 函数访问 scope 变 7
量时,JavaScript 会先搜索函数 f 的作用域,恰巧在 f 作用域里面搜索到 scope 变量,
所以上层作用域中定义的 scope 就被屏蔽了,但执行到 console.log 语句时,scope 还
没被定义,或者说初始化,所以得到的就是 undefined 值了。
8
我们还可以从另一个角度来理解:对于开发者来说,在访问未定义的变量或定义了但没
有初始化的变量时,获得的值都是 undefined。于是我们可以认为,无论在函数内什么地
方定义的变量,在一进入函数时就被定义了,但直到 var 所在的那一行它才被初始化,所
以在这之前引用到的都是 undefined 值。(事实上,JavaScript 的内部实现并不是这样,未 9
定义变量和值为 undefined 的变量还是有区别的。)
函数作用域的嵌套
接下来看一个稍微复杂的例子:
10