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循 ...
随机推荐
- 【ALB学习笔记】基于事件触发方式的串行通信接口数据接收案例
基于事件触发方式的串行通信接口数据接收案例 广东职业技术学院 欧浩源 一.案例背景 之前写过一篇<基于多线程方式的串行通信接口数据接收案例>的博文,讨论了采用轮询方式接收串口数据的情况. ...
- java 邮件发送工具类
首先需要下载mail.jar文件,我个人通常是使用maven中心库的那个: <dependency> <groupId>javax.mail</groupId> & ...
- Socket异步通信及心跳包同时响应逻辑分析。
有段时间没有更博了,刚好最近在做Socket通信的项目,原理大致内容:[二维码-(加logo)]-->提供主机地址和端口号信息(直接使用[ThoughtWorks.QRCode.dll]比较简单 ...
- 3,Spring Boot热部署
问题的提出: 在编写代码的时候,你会发现我们只是简单把打印信息改变了,就需要重新部署,如果是这样的编码方式,那么我们估计一天下来就真的是打几个Hello World就下班了.那么如何解决热部署的问题呢 ...
- select默认选中项颜色为灰色,选择后变为黑色(js实现)
<script> var unSelected = "#999"; var selected = "#333"; $(function () { $ ...
- Android系统--输入系统(十七)Dispatcher线程_分发dispatch
Android系统--输入系统(十七)Dispatcher线程_分发dispatch 1. 回顾 InputRead线程从输入设备当中得到输入事件 对于读到输入事件稍作处理,比如紧急事件,来电时候按下 ...
- 关于table表格td里内容是数字而且太长不换行的问题
<p>table{table-layout:fixed}</p><p>table td{word-wrap:break-word}</p><p&g ...
- MSDTC启用——分布式事务
一.前言 最近在做一个项目的时候使用了.NET中的System.Transactions(分布式事务),当项目开发完成以后,调用的时候遇到了MSDTC的问题,在查阅了相关资料后将这个问题解决了,大致的 ...
- 暑假学习计划:Day_1.JSP&Servlet&Tocat 环境搭建到基础的认识。
1.了解JSP和Servlet(百度了解即可). 2.了解B/S和C/S.分别是 浏览器/服务器 和 客户端/服务器. 其中 B/S 被称为瘦模式(主流模式). 3.了解并下载Tomcat服务器 ...
- FaceRank-人脸打分基于 TensorFlow 的 CNN 模型
FaceRank-人脸打分基于 TensorFlow 的 CNN 模型 隐私 因为隐私问题,训练图片集并不提供,稍微可能会放一些卡通图片. 数据集 130张 128*128 张网络图片,图片名: 1- ...