首先我们应该知道js引擎在读取js代码时会进行两个步骤:

  • 第一个步骤是解释。
  • 第二个步骤是执行。

所谓解释就是会先通篇扫描所有的Js代码,然后把所有声明提升到顶端,第二步是执行,执行就是操作一类的。

我们先来看个简单的变量提升案例吧


a = 'javascript';
var a;
console.log(a);//'javascript'

console.log(b);//undefined
var b='javascript'

遇到 script 标签的话 js 就进行预解析,将变量 var 和 function 声明提升,但不会执行 function,然后就进入上下文执行,上下文执行还是执行预解析同样操作,直到没有 var 和 function,就开始执行上下文。如:


a=5;
show();
var a;
function show(){};

预解析:


function show(){};
var a;
a=5;
show();

需要注意都是函数声明提升直接把整个函数提到执行环境的最顶端。

那么let/const和var又有什么区别呢??

  • let/const是使用区块作用域;var是使用函数作用域。
  • 在let/const声明之前就访问对应的变量与常量,会抛出ReferenceError错误;但在var声明之前就访问对应的变量,则会得到undefined。

console.log(aVar) // undefined
console.log(aLet) // causes ReferenceError: aLet is not defined
var aVar = 1
let aLet = 2

会出现这样的情况是因为let/const拥有“暂时性死区(TDZ)”。

什么是暂时性死区?

当程序的控制流程在新的作用域(module, function或block作用域)进行实例化时,在此作用域中的用let/const声明的变量会先在作用域中被创建出来,但因此时还未进行词法绑定,也就是对声明语句进行求值运算,所以是不能被访问的,访问就会抛出错误。所以在这运行流程一进入作用域创建变量,到变量开始可被访问之间的一段时间,就称之为TDZ(暂时死区)。

结论:let/const声明的变量,的确也是有提升(hoist)的作用。这个是很容易被误解的地方,实际上以let/const声明的变量也是会有提升(hoist)的作用。提升是JS语言中对于变量声明的基本特性,只是因为TDZ的作用,并不会像使用var来声明变量,只是会得到undefined而已,现在则是会直接抛出ReferenceError错误,而且很明显的这是一个在运行期间才会出现的错误。

ES6 规定暂时性死区和let、const语句不出现变量提升,主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。这样的错误在 ES5 是很常见的,现在有了这种规定,避免此类错误就很容易啦~

原文地址:https://segmentfault.com/a/1190000017352156

深入理解let和var的区别的更多相关文章

  1. 详解变量声明加 var 和不加 var 的区别

    在全局作用域中声明变量加 var 关键字和不加 var ,js 引擎都会将这个变量声明为全局变量,在实际运行时,两种声明方式的变量的行为也是几乎一致的.但是在全局作用域下是否声明一个变量的 时候加va ...

  2. 前端面试题:JS中的let和var的区别

    最近很多前端的朋友去面试被问到let和var的区别,其实阮一峰老师的ES6中已经很详细介绍了let的用法和var的区别.我简单总结一下,以便各位以后面试中使用. ES6 新增了let命令,用来声明局部 ...

  3. es6入门1-- let与var的区别详解

    一.前言 说到做到,现在暂时放了放JS模式的读书笔记,打算好好看看ES6,毕竟出了这么久了,还是靠JS吃饭的,都不好好学JS新特性,确实说不过去,我本来是想当读书笔记去记录ES6,但是这个确实是属于边 ...

  4. 在Javascript中 声明时用"var"与不用"var"的区别,== 和 ===的区别

    今天,被问到两个JS问题,当时没回答到重点,问题虽然看起来简单,但是细节却马虎不得,在此做下记录: 1. 在Javascript中 声明时用"var"与不用"var&qu ...

  5. IL角度理解for 与foreach的区别——迭代器模式

    IL角度理解for 与foreach的区别--迭代器模式 目录 IL角度理解for 与foreach的区别--迭代器模式 1 最常用的设计模式 1.1 背景 1.2 摘要 2 遍历元素 3 删除元素 ...

  6. JavaScript中变量声明有var和没var的区别

    JavaScript中变量声明有var和没var的区别 JavaScript中有var和没var的区别 Js中的变量声明的作用域是以函数为单位,所以我们经常见到避免全局变量污染的方法是 (functi ...

  7. css基础--深入理解opacity和rgba的区别

    欢迎访问我的个人博客:http://www.xiaolongwu.cn 前言 首先这两个都与透明度有关,那么他们之间有什么具体的区别呢?在实际工作中我们需要注意什么呢?请您接着往下看 语法 1. rg ...

  8. js中const,var,let区别(转载)

    js中const,var,let区别 来源:https://www.cnblogs.com/zzsdream/p/6372729.html 今天第一次遇到const定义的变量,查阅了相关资料整理了这篇 ...

  9. [js]js中变量带var和不带var的区别

    上图已说的很清晰了. 下面代码是赘述 <script> //带var和不带var的区别: // 1.只有带var的才可以预解释,所以在赋值的前操作不会报错. console.log(num ...

随机推荐

  1. THUSC2016 成绩单

    题目链接:Click here Solution: 我们设\(f[l][r][x][y]\)表示在原区间\(l\sim r\) 内还未被取走的值最大为\(x\)最小为\(y\)时的代价,这里我们只考虑 ...

  2. php 将几个变量合为数组,变量名和值对应

    <?php $firstname = "Bill"; $lastname = "Gates"; $age = "60"; $resul ...

  3. php的 strval函数

    官方的解释 PHP strval() 函数 PHP 可用的函数 strval() 函数用于获取变量的字符串值. PHP 版本要求: PHP 4, PHP 5, PHP 7 语法 string strv ...

  4. Redis大 key的发现与删除方法全解析

    个推作为国内第三方推送市场的早期进入者,专注于为开发者提供高效稳定的推送服务,经过9年的积累和发展,服务了包括新浪.滴滴在内的数十万APP.由于我们推送业务对并发量.速度要求很高,为此,我们选择了高性 ...

  5. JS基础_强制类型转换

    强制类型转换 将一个数据类型强制转换为其他的数据类型 类型转换主要指,将其他数据类型,转换为 string.number.boolean 1.将其他数据类型转换为string(返回值是强转后类型的值) ...

  6. LeetCode 198. 打家劫舍(House Robber)LeetCode 213. 打家劫舍 II(House Robber II)

    打家劫舍 题目描述 你是一个专业的小偷,计划偷窃沿街的房屋.每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报 ...

  7. C与指针学习笔记

    有些任务无法用其他语言实现,如直接访问硬件,但C却可以. C对数组下标引用和指针访问并不进行有效性检查,这可以节省时间,但你在使用这些特性时,就必须特别小心.

  8. CopyOnWriteArrayList使用

    1.在遍历操作数量大大超过可变操作是(add,set等等)使用.原因是其可变操作是通过对底层数据进行一次新的复制来实现的. 2.迭代器创建后,其不会反应列表的添加.移除或更改.其迭代器是”快照“风格的 ...

  9. docker —宝塔面板

    下载个单独的系统镜像 [root@git opt]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/nginx-tomcat ...

  10. https的那些坑

    1.时间 一些老手机不是系统自动对时,时间错误会报错. com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeExceptio ...