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循 ...
随机推荐
- Jmeter之分布式测试
1)Jmeter 是纯java 应用,对于CPU和内存的消耗比较大,并且受到JVM的一些限制: 一般情况下,依据机器配置,单机的发压量为300-600,因此,当需要模拟数以千计的并发用户时,使用单台机 ...
- Spring+SpringMVC+MyBatis深入学习及搭建(十三)——SpringMVC入门程序(二)
1.非注解的处理器映射器和适配器 1.1非注解的处理器映射器 前面我们配置的org.springframework.web.servlet.handler.BeanNameUrlHandlerMapp ...
- 性能百万/s:腾讯轻量级全局流控方案详解
WeTest 导读 全新的全局流控实现方案,既解决了目前流控的实现难点,同时保证运行稳定且流控准确的前提下,实现更简单,部署成本更低,容灾能力更强. 该方案组件化之后,可以推广到别的有需要的部门使用, ...
- PHPOffice/PHPExcel生成省市区三级联动的excel表格
最近公司需要用到一个省市区三级联动的excel表格,但是数据都在数据库,又太多,人工不好制作,就让我这个phper来帮忙啦. 主要用到的是excel的定义名称,数据验证.其中数据验证的列表只能是一列或 ...
- 介绍一个全局最优化的方法:随机游走算法(Random Walk)
1. 关于全局最优化求解 全局最优化是一个非常复杂的问题,目前还没有一个通用的办法可以对任意复杂函数求解全局最优值.上一篇文章讲解了一个求解局部极小值的方法--梯度下降法.这种方法对于求解精度不高 ...
- 2017年1月1日 App Store中的所有应用都必须启用 App Transport Security安全功能
2017年1月1日 App Store中的所有应用都必须启用 App Transport Security安全功能,否则极有可能被拒! 在WWDC 2016开发者大会上,苹果宣布了一个最后期限:到20 ...
- 关于hibernate的缓存使用(转)
原文链接:http://blog.csdn.net/woshichenxu/article/details/586361#t0 1. 关于hibernate缓存的问题: 1.1.1. ...
- JS遍历属性和方法
引用原文:http://www.cnblogs.com/lishenglyx/archive/2008/12/08/1350573.html#undefined <script language ...
- Entity Framework Core 执行SQL语句和存储过程
无论ORM有多么强大,总会出现一些特殊的情况,它无法满足我们的要求.在这篇文章中,我们介绍几种执行SQL的方法. 表结构 在具体内容开始之前,我们先简单说明一下要使用的表结构. public clas ...
- Spring AOP With AspectJ
一.AOP和拦截器 某些情况下,AOP和拦截器包括Filter能够实现同样的功能,一般都是请求即controller层的操作,这三个执行顺序为Filter>Interceptor>AOP, ...