深入理解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中的变量及变量作用域的主要内容,如果未能解决你的问题,请参考以下文章