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 ...
随机推荐
- Python语言学习前提:基础语法
一.变量 1.变量:存储数据.存储数据需要对应内存空间,基于变量的数据类型,解释器会分配指定内存,决定什么数据被存储到内存中. 变量数据类型:整数.小数.字符. 2.变量赋值:变量在使用前必须赋值,赋 ...
- 在select2插件中append下拉选,点击没反应的解决
今天前端大佬帮我解决了一个棘手的问题:克隆了已有系统的网页,尝试把复制下来的html改造成jsp.基本功能正常,然而点击新增按钮,出来的行无法点击下拉选,控制台也没报错. 项目用的是jeesite2. ...
- 基于Wiki的知识共享平台模型架构
一.引言 当今的全球化知识经济社会中呈现出信息泛滥和知识更新周期短的现象,知识管理逐渐成为现代企业管理中不容忽视的一环.虚拟企业是基于共识目标而组成的动态协作组织,成员参与的流动性与各成员之间地域分布 ...
- LTE-U/LAA
将LTE扩展至非授权频谱,得益于一个稳健的无线电通信线路,具有更好协调性的同步节点,以及以授权频谱为基点的载波聚合,LTE-U/LAA能提供比载波Wi-Fi更佳的网络性能和更强的用户体验,为移动运营商 ...
- SSH免密码登陆详解
为了更好的理解SSH免密码登陆原理,我们先来说说SSH的安全验证,SSH采用的是”非对称密钥系统”,即耳熟能详的公钥私钥加密系统,其安全验证又分为两种级别. 1. 基于口令的安全验证 这种方式使用用户 ...
- QTP 表格的导入导出异常信息 笔记
0 环境 系统环境:win7 1 操作 1.1 前言 与异常遍历结合 需要表格记录下来(读写) 代码大概跑了一下 若细节有错 请自行更改 1.2 导出 systemutil.Run "D:\ ...
- Go-Micro框架入门教程(一)---框架结构
Go语言微服务系列文章,使用golang实现微服务,这里选用的是go-micro框架,本文主要是对该框架的一个架构简单介绍. 1. 概述 go-micro是go语言下的一个很好的微服务框架. 1.服务 ...
- [LC] 250. Count Univalue Subtrees
Given a binary tree, count the number of uni-value subtrees. A Uni-value subtree means all nodes of ...
- python学习笔记(4)数据类型-元组
元组其实和列表一样,不一样的是,元组的值不能改变,一旦创建,就不能再改变了,比如说,要存数据库的连接信息,这个连接信息在程序运行中是不能被改变的,如果变了那数据库连不上了,就程序就完犊子了,这样的就可 ...
- linux系统开机静态分配ip地址
在/etc/sysconfig/network-scripts/ifcfg-eth0文件中 添加: IPADDR=192.168.1.100(设置静态地址) NETMASK=255.255.255.0 ...