前言

看了方应杭老师的一篇解释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声明的区别的更多相关文章

  1. ES6和ES5变量声明的区别(var let const)

    // es5的语法与es6的语法区别 // var let const console.log(name);//undefine,不会报错,因为变量声明会提到作用域的最前面 var name=&quo ...

  2. javascript精雕细琢(一):var let const function声明的区别

    目录 引言 一.var 二.let 三.const 四.function 五.总结 引言        在学习javascript的过程中,变量是无时无刻不在使用的.那么相对应的,变量声明方法也如是. ...

  3. JavaScript:学习笔记(7)——VAR、LET、CONST三种变量声明的区别

    JavaScript:学习笔记(7)——VAR.LET.CONST三种变量声明的区别 ES2015(ES6)带来了许多闪亮的新功能,自2017年以来,许多JavaScript开发人员已经熟悉并开始使用 ...

  4. var、let、const声明变量的区别

    let和var声明变量的区别:1.let所声明的变量只在let命令所在的代码块内有效.(块级作用域) for(let i=0;i<10;i++){ // ... } console.log(i) ...

  5. ES6之用let,const和用var来声明变量的区别

    var(掌握) 不区分变量和常量   用var声明的变量都是变量,都是可变的,我们可以随便对它进行运算操作.这样当多个人进行同一个项目时,区分变量和常量会越来越难,一不小心就会把设计为常量的数据更改了 ...

  6. var let const的一些区别

    var let const 都是来定义变量的. var let 作用域有些区别. const 类似于java中的常量的概念.即:只能给一个变量赋值一次,即指定一个引用. 举例来说: function ...

  7. JavaScript 中 var 和 let 和 const 关键字的区别

    var与let.const的区别 在最新的 ES6 中,新添加了两个用于变量声明的关键字 let 和 const 一.var声明的变量会挂载在window上,而let和const声明的变量不会: va ...

  8. 轻松弄懂var、let、const之间的区别

    ECMAScript 6(简称ES6)是JavaScript语言的下一代标准,于2015年6月正式发布,也称ECMAScript 2015. ES6的好处 ES6的出现为我们前端带来了很多方便之处,以 ...

  9. 微信小程序var和let以及const有什么区别

    微信小程序var和let以及const的区别: 在JavaScript中有三种声明变量的方式:var.let.const. var:声明全局变量,换句话理解就是,声明在for循环中的变量,跳出for循 ...

随机推荐

  1. C#读取excl(兼容office多种版本)

    要求:导入excl引用了using System.Data.OleDb,需要安装一个office Microsoft.ACE.OLEDB.12.0 office7以上版本 Microsoft.Jet. ...

  2. IE浏览器兼容问题(上)——html和css的兼容写法

    用户使用的浏览器五花八门,我们要保证每一种浏览器都能兼容我们的代码,不能要求用户去改变浏览器,那么就得在我们的代码上下功夫.此时我们要用到hack. HACK就是针对不同的浏览器写不同的HTML.CS ...

  3. 纯 CSS 实现波浪效果!

    一直以来,使用纯 CSS 实现波浪效果都是十分困难的. 因为实现波浪的曲线需要借助贝塞尔曲线. 而使用纯 CSS 的方式,实现贝塞尔曲线,额,暂时是没有很好的方法. 当然,借助其他力量(SVG.CAN ...

  4. JavaScript-DOM编程的一些常用属性

    一.Document常见属性 document.title // 设置文档标题等价于HTML的title标签 document.bgColor // 设置页面背景色 document.fgColor ...

  5. 【NOIP模拟】roads(最短路径转最小生成树)

    题目背景 SOURCE:NOIP2016-RZZ-1 题目描述 有 N 个城市,这些城市通过 M 条无向边互相连通,每条边有一个权值 Ci ,表示这条边的长度为 2^(Ci) ,没有两条边的长度是相同 ...

  6. (转)Linux(Centos)之安装Java JDK及注意事项

    场景:天下事有难易乎?为之,则难者亦易矣:不为,则易者亦难矣.人之为学有难易乎?学之,则难者亦易矣:不学,则易者亦难矣. 1 准备工作 下面配置jdk的方式在具有root权限时候能够执行.如果没有ro ...

  7. Redis各种数据结构性能数据对比和性能优化实践

    很对不起大家,又是一篇乱序的文章,但是满满的干货,来源于实践,相信大家会有所收获.里面穿插一些感悟和生活故事,可以忽略不看.不过听大家普遍的反馈说这是其中最喜欢看的部分,好吧,就当学习之后轻松一下. ...

  8. CentOS5.5中卸载自带jdk 安装自己的jdk

    因为需要使用JDK1.6的版本,但是RedHat6.4自带的JDK是1.7版本,因此需要卸载JDK1.7,安装JDK1.6的版本,我使用的JDK1.6版本为:jdk-6u45-Linux-x64.bi ...

  9. Android学习笔记- ButterKnife 8.0注解使用介绍

    前言: App项目开发大部分时候还是以UI页面为主,这时我们需要调用大量的findViewById以及setOnClickListener等代码,控件的少的时候我们还能接受,控件多起来有时候就会有一种 ...

  10. 走进STM32世界之Hex程序烧写

    多数51单片机(STC系列单片机)的初学者都知道,在51单片机初上电时,可以通过PC机上位机软件将程序引导至bootloader,从而将新程序的hex文件下载至单片机中,完成程序的升级或是更新.在32 ...