Javascript中的局部变量、全局变量的详解与var、let的使用区别
前言
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随笔

Javascript中的局部变量、全局变量的详解与var、let的使用区别的更多相关文章
- JavaScript中的鼠标滚轮事件详解
JavaScript中的鼠标滚轮事件详解/*Firefox注册事件*/ ~~~Firefox: addEventListener('DOMMouseScroll', handler, false)if ...
- JavaScript中typeof和instanceof深入详解
这次主要说说javascript的类型判断函数typeof和判断构造函数原型instanceof的用法和注意的地方. typeof 先来说说typeof吧.首先需要注意的是,typeof方法返回一个字 ...
- JavaScript 中 apply 、call 的详解
apply 和 call 的区别 ECMAScript 规范给所有函数都定义了 call 与 apply 两个方法,它们的应用非常广泛,它们的作用也是一模一样,只是传参的形式有区别而已. 原文作者:林 ...
- Javascript中的this关键字用法详解
在javascript里面,this是一个特殊的对象,它不像其他编程语言那样,是存储在实例中的值,直接指向此实例. 而是作为一个单独的指针,在不同的情况之下,指向不同的位置,这也是为什么我们会将它搞混 ...
- JavaScript中事件委托(事件代理)详解
在JavaScript的事件中,存在事件委托(事件代理),那么什么是事件委托呢? 事件委托在生活中的例子: 有三个同事预计会在周一收到快递.为签收快递,有两种办法:一是三个人在公司门口等快递:二是委托 ...
- javascript中6种基本数据类型详解
javascript中有5中数据类型(也称为基本数据类型):Undefined.Null.Boolean.Number和String,还有一种复杂数据类型——object,object本质是由一组键值 ...
- JavaScript中继承的实现方法--详解
最近看<JavaScript王者归来>中关于实现继承的方法,做了一些小总结: JavaScript中要实现继承,其实就是实现三层含义:1.子类的实例可以共享父类的方法:2.子类可以覆盖父类 ...
- JavaScript中定义类的方式详解
本文实例讲述了JavaScript中定义类的方式.分享给大家供大家参考,具体如下: Javascript本身并不支持面向对象,它没有访问控制符,它没有定义类的关键字class,它没有支持继承的exte ...
- Javascript中的apply与call详解
JavaScript中有一个call和apply方法,其作用基本相同,但也有略微的区别. 一.方法定义 1.call 方法 语法:call([thisObj[,arg1[, arg2[, [,.arg ...
随机推荐
- Maven打包时报Failed to execute goal org.apache.maven.plugins:maven-war-plugin:解决方案
问题现象: 用Maven打包时,报Failed to execute goal org.apache.maven.plugins:maven-war-plugin:2.2:war错误. 原因分析: 打 ...
- Linux图形界面与命令行界面切换
1.没有安装图形界面的Linux系统执行下面命令安装图形界面: yum groupinstall "GNOME Desktop" "Graphical Administr ...
- AtCoder Grand Contest 033
为什么ABC那么多?建议Atcoder多出些ARC/AGC,好不容易才轮到AGC…… A 签到.就是以黑点为源点做多元最短路,由于边长是1直接bfs就好了,求最长路径. #include<bit ...
- VBA引用管理加载宏
下载文件: VBA引用管理加载宏.rar 下载后,解压缩. Excel的 开发工具/加载项 在对话框中浏览 VBA引用管理.xlam VBA界面中,在工程右键菜单中出现:
- 浏览器加载、渲染html的顺序和页面优化
浏览器加载和渲染html的顺序 1. IE下载的顺序是从上到下,渲染(就是把请求的内容显示到浏览器屏幕上)的顺序也是从上到下,下载和渲染是同时进行的. 2. 在渲染到页面的某一部分时,其上面的所有部分 ...
- 二:MySQL的操作
1:创建数据库 create database bjpowernode ; 2:使用数据库 use bjpowernode; 3:导入数据库文件sql source 然后把SQL文件拖过来就可以了 ...
- mysql中in和exist的区别
mysql中in和exists的区别 -- in写法select * from A where A.id in (select bid from B ) and A.name in (select ...
- golang kafka clinet 内存泄露问题处理
go 内存泄露 新版本服务跑上一天内存占用20g,显然是内存泄露 内存泄露的问题难在定位 技术上的定位 主要靠 pprof 生成统计文件 之前写web项目 基于net/http/pprof 可以看到运 ...
- JS代码,从一个数组中得到连号的数并显示
JavaScript code function m() { var k = [1, 2, 7, 8, 9, 11, 22, 35, 36]; ) return; ; ; ; ; i < k.l ...
- Integrated writing|Independent writing
Integrated writing R-L-W时间20min,字数150-225个词,写多不扣分. Objective要求客观. Academic topics主题是生物环境地理历史 Indepen ...