前言

看了方应杭老师的一篇解释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. MySQL实现自动使用uuid作为主键以及解决不能调用触发器的一点思路

    这里使用触发程序实现此功能. 触发程序语法如下: Create trigger <tri_name> {before|after} {insert|update|delete} On &l ...

  2. docker~大叔对术语的解释

    回到目录 接触和使用docker已经有1年多了,起初对概念本身理解的不是很好,或者说,没有找到一本比较好的书,在自己的研究下,对docker一些基本的概念有了自己的一些认识和看法,现在分享给正在学习d ...

  3. 使用Nginx+CppCMS构建高效Web应用服务器(之三)

    使用Nginx+CppCMS构建高效Web应用服务器(之三) --充分利用服务器和客户端计算能力 欢迎测试,攻击:http://www.litelottery.com     网页右上角,选择博彩,演 ...

  4. 没写完。。51nod_1630: B君的竞技场(期望 概率)

    题目链接 根据 你可以认为B君的水平是在所有人中的等概率随机 ,设 每场中B君获胜的概率为p~U(0,1),在给定的x,y下至游戏结束B君的获胜场数为f(p) (这是一个关于p的函数), 由此

  5. 创建 Machine - 每天5分钟玩转 Docker 容器技术(46)

    对于 Docker Machine 来说,术语 Machine 就是运行 docker daemon 的主机.“创建 Machine” 指的就是在 host 上安装和部署 docker.先执行 doc ...

  6. (转)使用BigDecimal进行精确运算

    场景:在进行支付业务的金额计算时,通常采用BigDecimal类型的数据,并没有看到常见的int double类型,所以有必要好好学习下BigDecimal的常用用法. 1 误区 首先我们先来看如下代 ...

  7. Java之集合的遍历与迭代器

    集合的遍历 依次获取集合中的每一个元素 将集合转换成数组,遍历数组 //取出所有的学号, 迭代之后显示学号为1004-1009 Object[] c=map.keySet().toArray();// ...

  8. 给ubuntu的swap分区增加容量

    1.创建一个 Swap 文件. mkdir swap cd swap sudo dd if=/dev/zero of=swapfile bs=1024 count=100000 出现下列提示,上面命令 ...

  9. 几种常见排序算法原理&C语言实现

    一.冒泡排序(以下各法均以从小到大排序为例,定义len为数组array的长度) 原理:比较相邻元素的大小,对于每次循环,按排序的规则把最值移向数组的一端,同时循环次数依次减少. C代码实现 写法一: ...

  10. JavaSE中线程与并行API框架学习笔记——线程为什么会不安全?

    前言:休整一个多月之后,终于开始投简历了.这段时间休息了一阵子,又病了几天,真正用来复习准备的时间其实并不多.说实话,心里不是非常有底气. 这可能是学生时代遗留的思维惯性--总想着做好万全准备才去做事 ...