深入理解JS中的变量及变量作用域

Posted 轩悦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入理解JS中的变量及变量作用域相关的知识,希望对你有一定的参考价值。

JS的变量有两种,“全局变量”和“局部变量”。

“全局变量”声明在函数外部,可供所有函数使用,(全局变量属于window)而“局部变量”声明在函数体内部,只能在定义该变量的函数体内使用。

1.全局变量:(1)直接在函数外部声明的变量   var a=3

                     (2)在任何位置上,声明变量时没有var关键字,而是直接赋值的变量均为全局变量     s=3

2.局部变量:(1)在函数内部声明的变量 

                     (2)形参,参数变量天生就是局部变量

1 <script type="text/javascript">
2   function main() {  
3     n = 10;//这里的n为全局变量,可以被外部直接使用
4   }
5   main();
6   alert(n);
7 </script>

JS的作用有两种,“全局作用域”和“函数作用域”。

1.全局作用域:可以在程序的任何位置被访问

2.函数作用域:  仅能在函数调用时,内部被访问

注意:在函数体内,局部变量的优先级高于全局变量。

网上有一个很具有代表性的例子,在函数体外部和内部都申明了相同名字的变量,变量的作用域问题,例子如下:

 1 <script type="text/javascript">
 2   var n = 1;
 3   function test() {
 4     alert(n);  //这里的n并不是全局变量,原因是函数体第四行声明了一个重名的局部变量n, 
 5                  //如果把第四行n的声明注释掉,那么这里的显示1,为全局变量。
 6                 //所以得出结论:全局变量a被局部变量a覆盖了。
 7               //说明了JS函数在test()在执行前,函数体内的变量a都指向了局部变量.
 8             //但本行输出的a在执行过程中还没有被赋值,所以显示undefined。
 9     n = 2;
10     alert(n);
11     var n; //本行声明局部变量a
12     alert(n);
13   }
14     test();
15     alert(n);
16 </script>

上面代码的结果为:undefined 2 2 1; 原因就是函数体外部和内部都申明了相同名字的变量时,局部变量覆盖了全局变量。

外部怎么读取函数体内部的局部变量呢?

一般来说,只有函数体内部可以直接得到外部的全局变量,但是外部要得到函数体内部的局部变量是不行的。但是,通过在函数体内部再定义一个函数返回局部变量,再从外部调用函数就能实现了。

 1 <script type="text/javascript">
 2   function f1() {    
 3     var n = 10;    
 4     function f2() {//在f1()内部再定义f2(),通过f2()访问f1()中的局部变量      
 5       alert(n);    
 6     }    
 7     return f2;//返回f1()局部变量n
 8   }  
 9   var result = f1(); //在外部调用f1()函数,就能获取局部变量n的值
10   result(); // 10,即为n的值
11 </script>

函数中变量的声明提升

在程序执行前或函数调用前,将var声明的变量和function声明的函数提升当前作用域的顶部集中创建。

请看下面的例子:

1 var v = "hello";
2 (function(){
3   console.log(v);
4   var v = "world";
5 })();    结果为undefined
1 var v = "hello";
2 if(true){
3   console.log(v);
4   var v = "world";
5 }     结果为hello

上面的代码说明了3个问题:1,function作用域里的变量v遮盖了全局作用域变量v

             2,在function作用域内,变量v的声明被提升了

                                            3,javascript是没有块级作用域的函数是JavaScript中唯一拥有自身作用域的结构

上面的代码相当于:

1 var v = "hello";
2 (function(){
3   var v; //declaration hoisting
4   console.log(v);
5   v = "world";
6 })();

总结:当前作用域内的声明都会提升到作用域的最前面,包括变量和函数的声明。

1 (function(){
2   var a = "1";
3   var f = function(){};
4   var b = "2";
5   var c = "3";
6 })();

变量a,f,b,c的声明会被提升到函数作用域的最前面,如下

1 (function(){
2   var a,f,b,c;
3   a = "1";
4   f = function(){};
5   b = "2";
6   c = "3";
7 })();

请注意函数表达式并没有被提升,这也是函数表达式与函数声明的区别。进一步看二者的区别:

(function(){
  //var f1,function f2(){}; //声明提升,被隐式提升的声明
 
  f1(); //ReferenceError: f1 is not defined
  f2();
 
  var f1 = function(){};
  function f2(){}
})();

上面代码中函数声明f2被提升,所以在前面调用f2是没问题的。虽然变量f1也被提升,但f1提升后的值为undefined,其真正的初始值是在执行到函数表达式处被赋予的。所以只有声明是被提升的。

 

 

以上是关于深入理解JS中的变量及变量作用域的主要内容,如果未能解决你的问题,请参考以下文章

知识深入理解js闭包

javascript深入理解js闭包

javascript深入理解js闭包

javascript深入理解js闭包

javascript深入理解js闭包

(转)javascript深入理解js闭包