作用域(scope)指的是变量存在的范围。
在 ES5 的规范中,Javascript 只有两种作用域:
全局变量: 生命周期将存在于整个程序之内。 能被程序中任何函数或者方法访问。 在 JavaScript 内默认是可以被修改的。
函数外部声明的变量就是全局变量(global variable),它可以在函数内部读取
var v = 1;function f() {console.log(v);}f() // 1
上面的代码表明,函数f内部可以读取全局变量v。
函数作用域
函数作用域内,对外是封闭的,从外层的作用域无法直接访问函数内部的作用域!!!
在函数内部定义的变量,外部无法读取,称为“局部变量”(local variable)。
function bar() {var testValue = 'inner';}console.log(testValue); // 报错:ReferenceError: testValue is not defined
上面代码中,变量testValue在函数内部定义,所以是一个局部变量,函数之外就无法读取
函数内部定义的变量,会在该作用域内覆盖同名全局变量。
var v = 1;function f(){var v = 2;console.log(v);}f() // 2v // 1
上面代码中,变量v同时在函数的外部和内部有定义。结果,在函数内部定义,局部变量v覆盖了全局变量v。
补:对于var命令来说,局部变量只能在函数内部声明,在其他区块中声明,一律都是全局变量。
if (true) {var x = 5;}console.log(x); // 5
上面代码中,变量x在条件判断区块之中声明,结果就是一个全局变量,可以在区块之外读取。
函数的变量提升
var命令声明的变量,不管在什么位置,变量声明都会被提升到函数体的头部。
function foo(x) {if (x > 100) {var tmp = x - 100;}}// 等同于function foo(x) {var tmp;if (x > 100) {tmp = x - 100;};}
函数本身的作用域
函数本身也是一个值,也有自己的作用域。它的作用域与变量一样,就是其声明时所在的作用域,与其运行时所在的作用域无关。
var a = 1;var x = function () {console.log(a);};function f() {var a = 2;x();}f() // 1
上面代码中,函数x是在函数f的外部声明的,所以它的作用域绑定外层,内部变量a不会到函数f体内取值,所以输出1,而不是2。
function foo() {var x = 1;function bar() {console.log(x);}return bar;}var x = 2;var f = foo();f() // 1
上面代码中,函数foo内部声明了一个函数bar,bar的作用域绑定foo。当我们在foo外部取出bar执行时,变量x指向的是foo内部的x,而不是foo外部的x。
总之,函数执行时所在的作用域,是定义时的作用域,而不是调用时所在的作用域。
遇到复杂作用域的时候,可以按照如下方法进行判断: 1.函数在执行的过程中,先从自己内部找变量 2.如果找不到,再从创建当前函数所在的作用域去找, 以此往上 3.注意找的是变量的当前的状态
