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 ...
随机推荐
- mac 编程环境
新mac (EI Capitan),需要在python中使用xgboost,通过pip安装未成功. 配置pip cat $HOME/Library/Application\ Support/pip/p ...
- 表查询语句及使用-连表(inner join-left join)-子查询
一.表的基本查询语句及方法 from. where. group by(分组).having(分组后的筛选).distinct(去重).order by(排序). limit(限制) 1.单表查询: ...
- Java注解基础
0.背景 Java注解--Annotation产生于JDK5.作为code的特殊“标记”,注解可以在编译.类加载.运行时被读取,并执行处理. 开发利用注解在源码中嵌入补充信息,工具(代码分析.开发.部 ...
- platform 平台驱动——设备的写作流程
说明:在内核源码里会有很多已经实现的驱动,对于我们来说只需要写好设备文件即可,但是我们如何知道驱动需要那些数据,以及有哪些驱动呢? 解决: 1.首先在内核源码目录下执行执行菜单配置命令: make m ...
- P2486 [SDOI2011]染色 区间合并+树链剖分(加深对线段树的理解)
#include<bits/stdc++.h> using namespace std; ; struct node{ int l,r,cnt,lazy; node(,,,):l(l1), ...
- screen小脚本
# 创建screen,执行命令,最小化screen #!/usr/bin/env bash screen_name1=$"bdapi" # 检查screen是否存在,等于0.表示s ...
- android ijkplayer简单使用
class VideoPlayer : FrameLayout, TextureView.SurfaceTextureListener{ private var url:String? = null ...
- QQ消息群发助手(超级简单)
大家好!我开发的小工具,效果见动图: 下载地址 QQ群发助手.rar 代码: def Login(): global Flag try: bot.Login(['-q',v1.get()]) tkin ...
- [LC] 513. Find Bottom Left Tree Value
Given a binary tree, find the leftmost value in the last row of the tree. Example 1: Input: 2 / \ 1 ...
- 对Java8新的日期时间类的学习(二)
示例11 在Java中如何判断某个日期是在另一个日期的前面还是后面 这也是实际项目中常见的一个任务.你怎么判断某个日期是在另一个日期的前面还是后面,或者正好相等呢?在Java 8中,LocalDate ...