函数作用域
- 定义:
作用域(scope)指的是变量存在的范围。在 ES5 的规范中,JavaScript 只有两种作用域:
全局作用域:变量在整个程序中一直存在,所有地方都可以读取。
函数作用域:变量只在函数内部存在。
ES6 又新增了块级作用域。
- 对于顶层函数来说,函数外部声明的变量就是全局变量(global variable),它可以在函数内部读取。
var a=1;
function fn(){
console.log(a); // 1
}
fn(); // 1
上面的代码中,变量a
在函数fn
外部定义(即是全局变量a
),函数fn
内部的console.log(a)
可以读取全局变量a
。
- 在函数内部定义的变量,外部无法读取,称为“局部变量”(local variable)。
function fn(){
var a=1;
}
console.log(a); // ReferenceError: a is not defined
fn();
上面代码中,变量a
在函数fn
内部定义,所以是一个局部变量,函数fn
之外的console.log(a)
就无法读取变量a
。
- 函数内部定义的变量,会在该作用域内覆盖同名全局变量。
var a = 1;
function fn(){
var a = 2;
console.log(a); // 2
}
fn(); // 2
console.log(a); // 1
上面代码中,变量a
同时在函数的外部和内部都有定义。结果,在函数内部定义,局部变量a
覆盖了全局变量a
,(即函数fn
内部的console.log(a)
只读取var a=2
所以fn()
输出2)。
- 对于
var
命令来说,局部变量只能在函数内部声明,在其他区块中声明,一律都是全局变量。
if (true) {
var x = 5;
}
console.log(x); // 5
上面代码中,变量x
在条件判断区块之中声明,结果就是一个全局变量,可以在区块之外读取。
那么什么是作用域链呢?
var a=1;
function fn(){
console.log(a); // 1
}
fn(); // 1
var a = 1;
function fn(){
var a = 2;
console.log(a); // 2
}
fn(); // 2
从上面两段代码中,我们可以得知我们在查找变量a
时,先在函数作用域中(即函数fn
内部)查找并读取变量a
,如果没有找到,再去全局作用域中查找并读取。你会注意到,这是一个从内往外层查找(从下往上查找)的过程。我们把这个整个查找的过程称之为作用域链。
原理
- 函数在执行的过程中,先从自己内部找变量并读取。
- 如果找不到,再从创建当前函数所在的作用域去找, 以此往上。
- 注意找的是变量的当前的状态。