JS中的var、let、const三者的区别
ES5:var ES6:let、const
ES5中的作用域有---全局作用域、函数作用域
ES6中新增了---块级作用域(块级作用域由{}
包裹,if语句、for语句中的{}
也属于块级作用域)
var
- 没有块级作用域的概念
- 有全局作用域、函数作用域的概念
- 不初始化值默认为undefined
- 存在变量提升
- 全局作用域用var声明的变量会挂载到window对象下
- 同一作用域中允许重复声明
let
- 有块级作用域的概念
- 不存在变量提升
- 暂时性死区
- 不存在全局作用域的概念
- 同一块作用域中不允许重复声明
const
- 与let特性一样,仅有2个差别
- 区别1——必须立即初始化,不能留到以后赋值
- 区别2——常量的值不能改变
var关键字
var-------------(没有块级作用域的概念)
//Global Scope
{
var a = 10;
}
console.log(a); //10
上面代码中,在Global Scope(全局作用域)中,且在Block Scope(块级作用域){}
中,a
输出结果为10,由此可以看出var
声明的变量不存在block scope的概念
var-------------(有全局作用域、函数作用域的概念)
//Global Scope
var a = 10;
function checkscope(){
//Local Scope
var b = 20;
console.log(a); //10
console.log(b); //20
}
checkscope();
console.log(b); //ReferenceError: b is not defined
上面代码中,在Global Scope中用var
声明了a
,在checkscope函数中的Local Scope(本地作用域、函数作用域)中打印出了10,但是在Global Scope中打印的变量b
报错了。
var-------------(不初始化值默认为undefined)
//Global Scope
var a;
console.log(a); //undefined
上面代码中,在Global Scope中用var声明了a
,但没有初始化值,它的值默认为undefined
,这里是undefined
是undefined
类型,而不是字符串。
var-------------(存在变量提升)
//Global Scope
console.log(a); //undefined
var a = 10;
checkscope();
function checkscope(){
//Local Scope
console.log(a); //undefined
var a;
}
上面代码中,先打印了a
,然后用var声明变量a
。变量提升是因为JS需要经历编译和执行阶段。而js在编译阶段的时候,会搜集所有的变量声明并且提前声明变量。可以将这个过程形象地想象成所有的声明(变量)都会被“移动”到各自作用域的最顶端,这个过程被称为提升。
至于checkscope
函数中的变量a
为什么输出undefined
,自己去看作用域链。
var-------------(全局作用域用var声明的变量会挂载到window对象下)
//Global Scope
var a = 10;
console.log(a); //10
console.log(window.a); //10
console.log(this.a); //10
上面代码中,打印出了3个10,访问a
和window.a
或是this.a
都是等价的。举个例子:比如我要访问location
对象,使用location
可以访问,使用window.location
也可以访问,只不过window
对象可以省略不写,就像new Array()
和new window.Array()
是等价的。
var-------------(同一作用域中允许重复声明)
//Global Scope
var a = 10;
var a = 20;
console.log(a); //20
checkscope();
function checkscope(){
//Local Scope
var b = 10;
var b = 20;
console.log(b); //20
}
上面代码中,在Global Scope中声明了2次a
,以最后一次声明有效,打印为20。同理,在Local Scope也是一样的。
let关键字
let-------------(有块级作用域的概念)
{
//Block Scope
let a = 10;
}
console.log(a); //ReferenceError: a is not defined
上面代码中,打印a
报错,说明存在Block Scope的概念。
let-------------(不存在变量提升)
{
//Block Scope
console.log(a); //ReferenceError: Cannot access 'a' before initialization
let a = 10;
}
上面代码中,打印a
报错:无法在初始化之前访问。说明不存在变量提升。
let-------------(暂时性死区)
{
//Block Scope
console.log(a); //ReferenceError: Cannot access 'a' before initialization
let a = 20;
}
if (true) {
//TDZ开始
console.log(a); //ReferenceError: Cannot access 'a' before initialization
let a; //TDZ结束
console.log(a); //undefined
a = 123;
console.log(a); //123
}
上面代码中,使用let
声明的变量a
,导致绑定这个块级作用域,所以在let
声明变量前,打印的变量a
报错。
在用let/const
声明的变量会先在作用域中被创建出来,但因此时还未进行词法绑定,所以是不能被访问的,如果访问就会抛出错误。因此,在这运行流程进入作用域创建变量,到变量可以被访问之间的这一段时间,就称之为暂时死区。
简单的来说:使用let
命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
其实上面不存在变量提升的例子中,其实也是暂时性死区,因为它有暂时性死区的概念,所以它压根就不存在变量提升了。
let-------------(不存在全局作用域的概念)
<script>
var foo = 'foo';
function bar(){}
let a = 10;
console.log(a); //10
console.log(window.a); //undefined
</script>
图例-1
上面代码中,打印变量a
为10,但是打印window.a
为undefined
,说明它不会挂在到window对象下,其实window对象是个顶层对象,他与Global不是一个东西,只不过在ES5中设计的时候,就把在Global中声明的变量(全局变量)自动的挂载到了window这个顶层对象里面了,所以我们在使用var
声明全局变量的时候会自动把这个变量挂载到window对象里去。window对象与Global会互相挂钩。
图例-1是在Firefox Developer Edition中的Debugger显示的。
let-------------(同一块作用域中不允许重复声明)
{
//Block Scope
let A;
var A; //SyntaxError: Identifier 'A' has already been declared
}
{
//Block Scope
var A;
let A; //SyntaxError: Identifier 'A' has already been declared
}
{
//Block Scope
let A;
let A; //SyntaxError: Identifier 'A' has already been declared
}
## const关键字
### const-------------(必须立即初始化,不能留到以后赋值)
```
{
//Block Scope
const a; //SyntaxError: Missing initializer in const declaration
}
```
上面代码中,用`const`声明的变量`a`没有进行初始化,所以报错。
### const-------------(常量的值不能改变)
```
{
//Block Scope
const a = 10;
a = 20; //TypeError: Assignment to constant variable
}
```
上面代码中,用`const`声明了变量`a`且初始化为10,然后试图修改`a`的值,报错。
`const`实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。
JS中的var、let、const三者的区别的更多相关文章
- 【JS学习】var let const声明变量的异同点
[JS学习]var let const声明变量的异同点 前言: 本博客系列为学习后盾人js教程过程中的记录与产出,如果对你有帮助,欢迎关注,点赞,分享.不足之处也欢迎指正,作者会积极思考与改正. 总述 ...
- js中加“var”和不加“var”的区别
JavaScript 拥有动态类型.这意味着相同的变量可用作不同的类型: var x // x 为 undefined var x = 6; // x 为数字 var x = "Bill&q ...
- 关于js中for in和foreach in的区别
js 中for in 和foreach in的区别 两个的作用都用来遍历对象,但为什么有了for in语句了还要foreach in语句呢,后来看了下foreach in开发的文档,foreach i ...
- let、var、const声明的区别
前言 看了方应杭老师的一篇解释let的文章,对JavaScript中的声明有了深刻的理解,这里也就有了总结一下JavaScript中各种声明之间区别的这篇文章. JavaScript中变量声明机制 首 ...
- C#中??和?分别是什么意思? 在ASP.NET开发中一些单词的标准缩写 C#SESSION丢失问题的解决办法 在C#中INTERFACE与ABSTRACT CLASS的区别 SQL命令语句小技巧 JQUERY判断CHECKBOX是否选中三种方法 JS中!=、==、!==、===的用法和区别 在对象比较中,对象相等和对象一致分别指的是什么?
C#中??和?分别是什么意思? 在C#中??和?分别是什么意思? 1. 可空类型修饰符(?):引用类型可以使用空引用表示一个不存在的值,而值类型通常不能表示为空.例如:string str=null; ...
- JS中构造函数和普通函数有什么区别
JS中构造函数有普通函数有什么区别? 1.一般规则 构造函数都应该以 一个大写字母开头,eg: function Person(){...} 而非构造函数则应该以一个小写字母开头,eg: functi ...
- ES6中的var let const应如何选择
javascript世界里面的每个人都在说有关ECMAScript 6 (ES6,也称作ES 2015)的话题,对象的巨大变化 ( 类 , super() , 等), 函数 (默认参数等), 以及模块 ...
- javascript中的var,let,const关键字
文章:JavaScript 中 var 和 let 和 const 关键字的区别 比较全面的文章.
- js中call、apply和bind的区别
在JS中,这三者都是用来改变函数的this对象的指向的,他们有什么样的区别呢.在说区别之前还是先总结一下三者的相似之处:1.都是用来改变函数的this对象的指向的.2.第一个参数都是this要指向的对 ...
- js中数组遍历for与for in区别(强烈建议不要使用for in遍历数组)
js中遍历数组的有两种方式 var array=['a'] //标准的for循环 for(var i=1;i<array.length;i++){ alert(array[i]) } //for ...
随机推荐
- 配置路由器/交换机的Telnet登录
实验目的:给配置路由器/交换机管理IP地址.设置Telnet的登录帐号.密码. 第一步:配置路由器的名称.接口IP地址. Switch> Switch>en Switch# Switch# ...
- 自动驾驶汽车数据不再封闭,Uber 开源新的数据可视化系统
日前,Uber 开源了基于 web 的自动驾驶可视化系统(AVS),称该系统为自动驾驶行业带来理解和共享数据的新方式.AVS 由Uber旗下负责自动驾驶汽车研发的技术事业群(ATG)开发,目前该系统已 ...
- mybatis if test标签的使用
2019独角兽企业重金招聘Python工程师标准>>> 在使用mybatis 有时候需要进行判断的. 而我们知道mybatis获取值有两种方式 #{}和${}的. 那么,在mybat ...
- qemu-img压缩磁盘操作
2019独角兽企业重金招聘Python工程师标准>>> qemu-img convert -c -f qcow2 -O qcow2 /data/data1.disk /opt/dat ...
- Nginx模块开发(2)————下载文件
Nginx的HTTP模块下载文件和传送缓冲区的字符串差不多,只需将文件标志置为1即可,我转送的文件是mp3的,所以HTTP的那个mine 类型要写为audio/mp3,二话不说了,贴代码,代码和之前那 ...
- 在web中使用shiro(会话管理,登出,shiro标签库的使用)
在shiro的主配置文件中配置,登出的请求经过的过滤器就可以了,在shiro的过滤器中有一个名称为logout的过滤 器专门为我们处理登出请求: 一.shiro会话管理器 shiro中也提供了类似于w ...
- Golang 实现 Redis(5): 使用跳表实现 SortedSet
本文是使用 golang 实现 redis 系列的第五篇, 将介绍如何使用跳表实现有序集合(SortedSet)的相关功能. 跳表(skiplist) 是 Redis 中 SortedSet 数据结构 ...
- shell 条件结构之 if 语句使用总结
文章目录 #条件判断的格式 [ exp ] [[ exp ]] test exp 注意: exp 与 "["."]"括号之间必须要有空格,否则会报语法错误: [ ...
- .NET分离exe和dll在不同的目录让你的程序更整洁
1.引言 在一个项目开发中一般都是把引用的dll放在根目录下,随着项目的日益增大,根目录下的dll文件就会越来越多,合理规划这些dll的存放地址,可以使整个项目更加的规范与美观.这篇文章就为大家介绍关 ...
- SVN 分支代码合并到主线
SVN 分支代码合并到主线 步骤一安装TortoiseSVN 客户端,在本地 checkout主线代码 步骤二:创建branches分支 步骤三.branches修改提交代码 步骤四:分支代码合并到主 ...