作用域(scope)指的是变量存在的范围。Javascript只有两种作用域:一种是全局作用域,变量在整个程序中一直存在,所有地方都可以读取,在全局作用域中声明的变量称为全局变量;另一种是局部作用域,变量只在函数内部存在,此时的变量被称为局部变量。
在全局作用域中声明的变量称为全局变量,也就是在函数外部声明。它可以在函数内部读取。
1 var a=1; 2 function keith(){ 3 return a; 4 } 5 console.log(keith()) //1
上面代码中,全局作用域下的函数keith可以在内部读取全局变量a。
在函数内部定义的变量,只能在内部访问,外部无法读取,称为局部变量。注意这里必须是在函数内部声明的变量。
1 function keith(){ 2 var a=1; 3 return a; 4 } 5 console.log(a) //Uncaught ReferenceError: a is not defined
在上面代码中,变量a在函数内部定义,所以是一个局部变量,外部无法访问。
函数内部定义的变量,会在该作用域下覆盖同名变量。注意以下两个代码段的区别。
1 var a = 2; 2 3 function keith() { 4 var a = 1; 5 console.log(a); 6 } 7 keith(); //1 8 9 var c = 2; 10 11 function rascal() { 12 var c = 1; 13 return c; 14 } 15 console.log(c); //2 16 console.log(rascal()); //1
上面代码中,变量a和c同时在函数的外部和内部有定义。结果,在函数内部定义,局部变量a覆盖了全局变量a。
注意,对于var命令来说,局部变量只能在函数内部声明。在其他区块声明,一律都是全局变量。比如说if语句。
1 if (true) { 2 var keith=1; 3 } 4 console.log(keith); //1
从上面代码中可以看出,变量keith在条件判断区块之中声明,结果就是一个全局变量,可以在区块之外读取。但是这里如果采用ES6中let关键字,在全局作用域下是无法访问keith变量的。
3.2:函数内部的变量声明提升
与全局作用域下的变量声明提升相同,局部作用域下的局部变量在函数内部也会发生变量声明提升。var命令声明的变量,不管在什么位置,变量声明都会被提升到函数体的头部。
1 function keith(a) { 2 if (a > 10) { 3 var b = a - 10; 4 } 5 } 6 7 function keith(a) { 8 var b; 9 if (a > 10) { 10 b = a - 10; 11 } 12 }
上面两个函数段是相同的。
3.3:函数本身的作用域
函数本身也是一个值,也有自己的作用域。它的作用域与变量一样,就是其声明时所在的作用域,与其运行时所在的作用域无关。
1 var a = 1; 2 var b = function() { 3 console.log(a); 4 }; 5 function c() { 6 var a = 2; 7 b(); 8 } 9 c(); //1 10 11 var a = 1; 12 var b = function() { 13 return a; 14 }; 15 function c() { 16 var a = 2; 17 return b(); 18 } 19 console.log(c()); //1