let、var、const声明的区别
前言
看了方应杭老师的一篇解释let的文章,对JavaScript中的声明有了深刻的理解,这里也就有了总结一下JavaScript中各种声明之间区别的这篇文章。
JavaScript中变量声明机制
首先,我对JavaScript中所有声明都存在提升这个观点是认同的!
平时大家所讲的变量的声明,在JavaScript中一般是存在创建create、初始化initialize 和赋值assign三个过程的,其中函数声明也是一样有这三个过程的。在这三个过程中:
创建:即在变量所在作用于头部抛出变量,仅仅是抛出,是不能被使用的;
初始化:在变量初始化之前变量是不能被使用的,初始化只有一次,初始化之后变量可以使用;
赋值:即覆盖初始化的值
在let、var、const(包括函数声明)的声明过程中,他们的创建create、初始化initialize 和赋值assign是有区别的。
let
let是ECMAScript2015(ES6)中新增的变量声明方式,let语句可以声明一个块级作用域的变量。
在同一个函数或同一个作用域中用let重复定义一个变量将引起 TypeError
if (true) {
let foo;
let foo; // TypeError thrown.
}
在let语句中,创建create、初始化initialize 和赋值assign的过程如下:
if (true) {
let foo
console.log(foo) //undefined
foo = 'str'
console.log(foo) //"str"
}
通过上面代码可以看出let语句是如下过程的:
第一步:在块级作用域中,找到let语句并声明提升,创建foo变量,但是在初始化之前使用是会报错的(如下面代码);
第二步:执行let foo,let语句使得foo变量被初始化,初始化的过程是可选的,可以let foo初始化foo为undefined,也可以let foo = 123初始化foo为123.初始化之后变量可以使用;
第三步:执行foo = 'str',foo变量可以被赋值语句覆盖
if (true) {
console.log(foo) //Uncaught ReferenceError: foo is not defined
let foo;
}
所以说,let声明中在初始化之前是存在“暂时性死区”的。
还有值得注意的是,初始化只能一次,如果变量初始化失败,则会存在一个该变量既不能赋值又不能使用的BUG,如下图:

因为let foo = foo导致初始化失败,所以导致了foo所在作用域都是foo变量只创建而未被初始化,所以foo所在作用域都会是foo变量的“暂时性死区”
var
var声明是函数作用域。
众所周知,var声明是有变量提升的,有了上文的let声明的理解,也就对var理解起来更加轻松了。
(function() {
console.log(f) //undefined
var f = 'str' //
console.log(f) //"str"
}())
var声明的过程:
第一步:在函数作用域中,找到var语句,f变量得到声明提升到作用域顶部,创建f变量并初始化为undefined,在赋值之前f的值就是undefined;
第二步:执行f = 'str',f变量被赋值为'str'
所以,在执行var f = 'str' 之前,打印的f的值为undefined
const
const声明创建了一个常量
const和let比较像,也是块级作用域,区别就是,const在定义的时候必须初始化,而且不能被赋值

如上图,const在定义时必须初始化,否则会报错Uncaught SyntaxError: Missing initializer in const declaration;const是常量,声明之后不能再次赋值,否则会报错Uncaught TypeError: Assignment to constant variable
函数声明
函数声明在JavaScript存在变量提升,这也被众多开发者做开发所常用。
fn()
function fn(){
console.log(this)
}
函数声明的过程:
第一步:在作用域中,找到function语句,将fn函数声明提升到作用域顶部,创建fn函数,初始化并赋值为
function fn(){console.log(this)};
第二步:执行fn()
即函数声明是在找到function语句后,作用域顶部创建、初始化和赋值一步到位的
总结
在MDN关于let讲解中,说let没有声明,也许是考虑到更容易被开发者接受和理解吧,但是我认为JavaScript中所有声明都存在提升是正确的。
最后用一个表格总结一下let、var、const声明的区别吧
| --- | let | var | const |
|---|---|---|---|
| 变量or常量 | 变量 | 变量 | 常量 |
| 作用域 | 块级作用域 | 函数作用域 | 块级作用域 |
| 创建 | 作用域顶部创建 | 作用域顶部创建 | 作用域顶部创建 |
| 初始化 | let语句 | 作用域顶部 | const语句 |
| 赋值 | 可以赋值 | 可以赋值 | 报错 |
| 重复声明 | 报错 | 可以重复声明 | 报错 |
| 暂时性死区 | 有 | 没有 | 有 |
本文首发在个人博客yoowin.me,欢迎访问。
let、var、const声明的区别的更多相关文章
- ES6和ES5变量声明的区别(var let const)
// es5的语法与es6的语法区别 // var let const console.log(name);//undefine,不会报错,因为变量声明会提到作用域的最前面 var name=&quo ...
- javascript精雕细琢(一):var let const function声明的区别
目录 引言 一.var 二.let 三.const 四.function 五.总结 引言 在学习javascript的过程中,变量是无时无刻不在使用的.那么相对应的,变量声明方法也如是. ...
- JavaScript:学习笔记(7)——VAR、LET、CONST三种变量声明的区别
JavaScript:学习笔记(7)——VAR.LET.CONST三种变量声明的区别 ES2015(ES6)带来了许多闪亮的新功能,自2017年以来,许多JavaScript开发人员已经熟悉并开始使用 ...
- var、let、const声明变量的区别
let和var声明变量的区别:1.let所声明的变量只在let命令所在的代码块内有效.(块级作用域) for(let i=0;i<10;i++){ // ... } console.log(i) ...
- ES6之用let,const和用var来声明变量的区别
var(掌握) 不区分变量和常量 用var声明的变量都是变量,都是可变的,我们可以随便对它进行运算操作.这样当多个人进行同一个项目时,区分变量和常量会越来越难,一不小心就会把设计为常量的数据更改了 ...
- var let const的一些区别
var let const 都是来定义变量的. var let 作用域有些区别. const 类似于java中的常量的概念.即:只能给一个变量赋值一次,即指定一个引用. 举例来说: function ...
- JavaScript 中 var 和 let 和 const 关键字的区别
var与let.const的区别 在最新的 ES6 中,新添加了两个用于变量声明的关键字 let 和 const 一.var声明的变量会挂载在window上,而let和const声明的变量不会: va ...
- 轻松弄懂var、let、const之间的区别
ECMAScript 6(简称ES6)是JavaScript语言的下一代标准,于2015年6月正式发布,也称ECMAScript 2015. ES6的好处 ES6的出现为我们前端带来了很多方便之处,以 ...
- 微信小程序var和let以及const有什么区别
微信小程序var和let以及const的区别: 在JavaScript中有三种声明变量的方式:var.let.const. var:声明全局变量,换句话理解就是,声明在for循环中的变量,跳出for循 ...
随机推荐
- Python基础之常用模块(三)
1.configparser模块 该模块是用来对文件进行读写操作,适用于格式与Windows ini 文件类似的文件,可以包含一个或多个节(section),每个节可以有多个参数(键值对) 配置文件的 ...
- 会话跟踪Cookie与Session
会话跟踪用来跟踪用户的整个会话,常用的是Session和Cookie.Cookie通过客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份. 1.Cookie 1.1概念及使 ...
- 流畅python学习笔记:第十五章:上下文管理器
在开始本章之前,我们首先来谈谈try-excep..final模块.在Python中,进行异常保护的最多就是用try..except..final.首先来看下下面的代码.进行一个简单的除法运算.为了防 ...
- IEnumerable & IEnumerator
IEnumerable 只有一个方法:IEnumerator GetEnumerator(). INumerable 是集合应该实现的一个接口,这样,就能用 foreach 来遍历这个集合. IEnu ...
- 写移动端必备的meta标签
<meta name="renderer" content="webkit" /> <meta http-equiv="X-UA-C ...
- .NET Core 2.0和ASP.NET Core 2.0正式版抢先体验
.NET Core 2.0和ASP.NET Core 2.0正式版抢先体验 .NET Standard 2.0 is final Broad platform support. .NET Standa ...
- 为什么要学习Java EE
Java EE学习之路 学习了Java SE,还只是完成“万里长征”的第一步. 接下来选择学习Java EE或是Java ME(或者你还想不断深入学习Java SE,只要你喜欢,你可以一直深入下去,就 ...
- "=="和equals方法究竟有什么区别?
(单独把一个东西说清楚,然后再说清楚另一个,这样,它们的区别自然就出来了,混在一起说,则很难说清楚) ==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同, ...
- Appium总结
运行case前,最好在case前加入等待,以免activity还未关闭,就开始定位或其他操作(如果case总报错,则考虑此问题): swipe效果: Thread.sleep(2000); ...
- angular学习(四)-- Controller
1.4 控制器:Controller ng 中的控制器用来对 scope 进行操作 包括初始化数据和定义事件响应函数等 ng 用来解耦业务逻辑层和视图层的关键 controller 操作 scope, ...