首页 > 代码库 > JavaScript的变量作用域深入理解

JavaScript的变量作用域深入理解

在学习JavaScript的变量作用域之前,我们应当明确几点:
a、JavaScript的变量作用域是基于其特有的作用域链的。
b、JavaScript没有块级作用域。
c、函数中声明的变量在整个函数中都有定义。

<script>var x = 1;function outer() {    var y = 2;    function inner() {        var z = 4;        alert(x);    }    inner(); }outer(); </script>

alert(x)这句代码,JavaScript首先在inner函数中查找是否定义了变量x,如果定义了则使用inner函数中的x变量;
如果inner函数中没有定义x变量,JavaScript则会继续在rainman函数中查找是否定义了x变量,在这段代码中outer函数体内没有定义x变量,则JavaScript引擎会继续向上(全局对象)查找是否定义了x;
在全局对象中我们定义了x = 1,因此最终结果会弹出‘1‘。
作用域链:JavaScript需要查询一个变量x时,首先会查找作用域链的第一个对象,如果以第一个对象没有定义x变量,JavaScript会继续查找有没有定义x变量,如果第二个对象没有定义则会继续查找,以此类推。
上面的代码涉及到了三个作用域链对象,依次是:inner、outer、window。

 

2、函数体内部,局部变量的优先级比同名的全局变量高。

<script>var x = 1;function check() {    var x = 100; //定义局部变量x    alert(x); //这里会弹出 100}check();alert(x); //这里会弹出1</script>

 

3、JavaScript没有块级作用域。
这一点也是JavaScript相比其它语言较灵活的部分。
仔细观察下面的代码,你会发现变量a、b、c作用域是相同的,他们在整个inner函数体内都是全局的。

<script>function inner() {    var a = 0;    if (1) {        var b = 0;        for (var c = 0; c < 3; c++) {            alert(c); // 分别弹出 0 1 2        }        alert(c); //弹出3     }    alert(a); //弹出0    alert(c); //弹出3 }inner();alert(c); //不弹值 ,如果将var c = 0 中 var 去掉,则会弹出 3</script>

对于有块级作用域的语言来说,for语句中定义并初始化的变量i在循环外是无法访问的,而在javascript中,for语句中定义的变量c在循环结束后,依旧会存在于循环外部的执行环境(作用域)中,在这里c的作用域是全局环境。具体来说就是:使用var关键字声明变量时,这个变量会自动添加到距离最近的可用环境中。对于函数而言,这个最近的环境就是函数的局部环境。
如果变量在未经声明的情况下被初始化,则该变量会被自动添加到全局环境。
不过有时候的确很需要块级作用域来解决一些问题,这时候我们就可以使用匿名函数来模仿块级作用域。
匿名函数就是没有名字的函数,有时候也被称为拉姆达(lamda)函数。形式如下:
(function(){
//块级作用域
})();
以上代码的意思是:首先定义并立即调用一个匿名函数。将函数声明包含在圆括号中,表示它实际上是一个函数表达式。而紧随其后的另一对圆括号表示立即调用这个函数。
当匿名函数执行完毕,其作用域链立即销毁,从而可以减少闭包占用资源问题。

 

4、函数中声明的变量在整个函数中都有定义。 

<script>function outer() {    var x = 1;    function inner() {        x = 100;    }    inner();     alert(x); //弹出 100}outer(); </script>

上面代码说明了,变量 x 在整个 outer 函数体内都可以使用,并可以重新赋值。
由于这条规则,会产生“匪夷所思”的结果,观察下面的代码。

<script> var x = 1;function inner() {    alert(x); //弹出 ‘undefined‘,而不是1    var x = 2;    alert(x); //弹出 2}inner();</script> 

这是由于在函数 inner 内局部变量 x 在整个函数体内都有定义 var x= 2,进行了声明 ) , 所以在整个 inner 函数体内隐藏了同名的全局变量 x 。
这里之所以会弹出 ‘undefined‘ 是因为,第一个执行 alert(x) 时,局部变量 x 仍未被初始化。

所以上面的 inner 函数等同于下面的函数。 

<script> function inner() {    var x;    alert(x);    x = 2;    alert(x);}</script> 

 

5、未使用var关键字定义的变量都是全局变量。
这也是JavaScript新手常见的错误,无意之中留下的许多全局变量。

<script> function inner() {    x = 100; // 声明了全局变量x并进行赋值}inner();alert(x); //会弹出100</script> 

 

6、全局变量都是window对象的属性 

<script> var x = 100;alert(window.x); //弹出100alert(x);</script> 

等同于下面的代码 

<script> window.x = 100; alert( window.x ); alert(x) </script> 

 

JavaScript的变量作用域深入理解