前言
Javascript中的变量定义方式有以下三种方式:
1、直接定义变量,var与let均不写;
a = 10;
2、使用var关键字定义变量
var a = 10;
3、使用let关键字定义变量
let a = 10;
这三种方式有什么区别呢?
JavaScript全局变量和局部变量又是什么呢?
可以带着这两个问题往下看。
变量的作用域
变量是有作用域的,大多数语言中的变量的作用域都有全局变量和局部变量之分。
首先我们建立一个文件test1.html,从中输入以下代码:
<script type="text/javascript">
//在函数外使用var关键字声明变量test_var1
var test_var1 = "变量1";
//定义函数testFun
function testFun(){
//在函数中定义变量没加任何关键字的变量test_var2
test_var2 = "变量2";
//函数内使用var关键字定义的test_var3
var test_var3 = "变量3";
}
//函数执行
testFun();
alert(test_var1 + "\n" + test_var2);
alert(test_var3);
</script>
在浏览器打开我们的html页面,可以看到只弹出了一个弹窗:
第二个弹窗为什么没有成功弹出呢?
我们按F12,看一下报错内容:
由此可以看出 test_var3 在函数执行后是没有被定义的。说明在函数体内用 var 关键字声明的变量 test_var3 是局部变量;
在函数体外使用 var 关键字定义的变量test_var1 和在函数体内未用任何关键字定义的变量 test_var2 是全局变量。
得出结论:
在函数体外使用var关键字定义的变量和在函数体内未用任何关键字声明的变量是全局变量,在函数体内使用var关键字声明的变量是局部变量。
var声明的全局变量和局部变量同名
我们建立一个文件test2.html,从中输入以下代码:
<script type="text/javascript">
//在函数外使用var关键字声明变量test_var
var test_var = "函数体外的变量";
//定义函数testFun
function testFun(){
//函数内使用var关键字声明变量test_var
var test_var = "函数体内的变量";
//弹窗弹出test_var
alert(test_var);
}
//函数执行
testFun();
alert(test_var);
</script>
打开该文件,会弹出两次弹窗,分别是:
点击确定后还会弹窗一次:
在函数体外定义的全局变量test_var,但是在函数体内又定义了局部变量test_var ,在函数中弹出的test_var是函数体内的局部变量覆盖函数体外的全局变量的结果,当离开函数后,局部变量失效,将会看到全局变量。
JavaScript中的变量有块范围吗?
在Java、C、C++等语言中,在 if块 ,循环块中定义的变量,出了该块之后将,不能继续访问。那JavaScript中是否也如此呢?
我们建立一个文件test3.html,从中输入以下代码:
<script type="text/javascript">
//定义函数testFun
function testFun(){
//函数内使用var关键字声明变量test_var
var test_var1 = "1";
//if代码块
if(test_var1 == "1"){
//定义变量test_var2
var test_var2 = 10;
//for代码块
for(var i = 0; i < 5; i++){
//打印输出i
document.write(i);
}
}
//在if块外访问test_var2
alert(test_var2);
//在循环体外访问i
alert(i);
}
//函数执行
testFun();
</script>
我们可以看到两个弹窗:
并且能看到页面上的输出
由此我们可以知道:
在函数体内中的 if 块和循环体内定义的变量,在函数内都是可以访问的。
变量提升
前面介绍中已经知道:局部变量和全局变量同名时,局部变量会覆盖全局变量。
我们定义test4.html,输入以下代码:
<script type="text/javascript">
//在函数外使用var关键字声明变量test_var
var test_var = "函数外的test_var";
//定义函数testFun
function testFun(){
//打印输出test_var
document.writeln(test_var + "<br>");
//函数内使用var关键字定义的test_var
var test_var = "函数内的test_var";
//再次打印输出test_var
document.writeln(test_var + "<br>");
}
//函数执行
testFun();
</script>
输出如下:
在输出全局变量时,居然输出的是underfined,这是什么情况呢?
这便是JavaScript的变量提升机制起了”作用“。下面介绍一下变量提升:
在函数体内变量声明总会被解释器”提升“到函数体的顶部,
那么上面的代码,会变成如下情况:
<script type="text/javascript">
//在函数外使用var关键字声明变量test_var
var test_var = "函数外的test_var";
//定义函数testFun
function testFun(){
//声明被提升到顶部,但是未被赋值
var test_var;
//打印输出test_var
document.writeln(test_var + "<br>");
//给test_var赋值
test_var = "函数内的test_var";
//再次打印输出test_var
document.writeln(test_var + "<br>");
}
//函数执行
testFun();
</script>
由此可见,变量提升只提升声明部分,不提示赋值部分。
我们定义test5.html,输入以下代码:
<script type="text/javascript">
//在函数外使用var关键字声明变量test_var1
var test_var1 = "函数外的test_var1";
//在函数外使用var关键字声明变量test_var2
var test_var2 = "函数外的test_var2";
//定义函数testFun
function testFun(){
//打印输出test_var1
document.writeln(test_var1 + "<br>");
//打印输出test_var2
document.writeln(test_var2 + "<br>");
//for循环的条件为假不会被执行
for(;-1>5;){
//在函数内使用var关键字声明变量test_var1
var test_var1 = "函数内的test_var1";
}
return;
//return后面的语句不会被执行
//在函数内使用var关键字声明变量test_var2
var test_var2 = "函数内的test_var2";
}
//函数执行
testFun();
</script>
输出如下:
在函数内的test_var1 和test_var2 的变量定义根本不会被执行,为何还是输出undefined呢?
这也是变量提升起的”作用“。
let关键字定义变量
从前面我们可以看到,var定义的变量没有块作用域,还有变量提升机制,为了克服这些问题,便引入了let关键字。
我们定义test6.html,输入以下代码:
<script type="text/javascript">
//循环体
for(let v = 0;v < 5;v++){
//在循环体内输出v
console.log(v);
}
//在循环体外输出v
console.log(v);
</script>
按F12,打开console,看到输出如下:
可以看到在循环体外不能访问循环体内定义的变量。
我们定义test7.html,输入以下代码:
<script type="text/javascript">
//在函数外使用let关键字声明变量test_var
let test_var = "函数外的test_var";
//定义函数testFun
function testFun(){
//打印输出test_var
console.log(test_var);
//在函数内使用let关键字声明变量test_var
let test_var = "函数内的test_var"
//打印输出test_var
console.log(test_var);
}
//函数执行
testFun();
</script>
按F12,打开console,看到输出如下:
这是因为函数内有和全局变量同名的局部变量,会覆盖掉全局变量,但是let关键字声明的变量并没有提升机制,所以会报错。
小结
本文介绍了JavaScript中的局部变量和全局变量的知识和var,let声明变量的区别。给我们的启示是如果浏览器支持let关键字,那么就尽量用let来避免变量提升机制等情况。
欢迎关注
扫下方二维码即可关注,微信公众号:code随笔