前言

看了方应杭老师的一篇解释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. promise异步编程的原理

    一.起源 JavaScript中的异步由来已久,不论是定时函数,事件处理函数还是ajax异步加载都是异步编程的一种形式,我们现在以nodejs中异步读取文件为例来编写一个传统意义的异步函数: var ...

  2. 自己实现的数据表格控件(dataTable),支持自定义样式和标题数据、ajax等各种自定义设置以及分页自定义

    一.前言 也没什么好说的嘛,用了蛮多github上开源的能够实现dataTable功能的表格插件,不过都默认绑定样式啊,数据格式也设定的比较死,所以忍不住自己实现了一个简单的可自定义样式和自定义数据返 ...

  3. oracle分组-神奇的cube和rollup

    先看代码: 表结构如下: emp表 EMPNO                                     NOT NULL NUMBER(4) ENAME                 ...

  4. ETL作业自动化调度软件TASKCTL4.5安装程序是选项解释

    下文仅针对TASKCTL4.5有效,在执行安装程序后,会看到安装程序有4个选项,其中,1和2是需要了解的. 1, 典型安装: 这个选项是单机部署,在第一次使用TASKCTL的时候,我用的是这种安装方式 ...

  5. ECMAscript6新特性之解构赋值

    在以前,我们要对变量赋值,只能直接指定值.比如:var a = 1;var b = 2;但是发现这种写法写起来有点麻烦,一点都不简洁,而在ECMAScript6中引入了一种新的概念,那就是" ...

  6. efcore 配置链接sqlserver 记录

    本文将在asp.net core api 项目中使用efcore corefirst模式 简单配置链接sqlserver数据库,以及简单的数据库迁移操作 一 新建项目 1. 首先我们先用vs2017 ...

  7. 如何使用Androidstudio创建一个新项目

    首先打开AS,然后 选择第一个选项Start a new Android Studio project 填写包名和项目名,点击next 选择项目类型,点击next 选择UI类型(都是死丢丢帮你生成的) ...

  8. swift3.0 移除当前页面的前一个页面

    用的是以下的跳转方式 self.navigationController?.pushViewController(viewController, animated: true) 在当前页面移除方式 s ...

  9. python--DenyHttp项目(2)--ACM监考客户端1.0版

    修复了: 360搜索可以使用的漏洞 更新版本,上一版本复制的Hosts文件保留的漏洞 #coding:gbk import os import sys from subprocess import * ...

  10. canvas的学习

    canvas的学习 一. //获取画布 var mycanvasEle = document.getElementById("mycanvas");二. //内容 var ctx ...