一篇文章带你深入理解ES6let和const命令

let命令

块级作用域

       ES6新增了let命令,用于声明变量,其用法类似于var,但是所声明的变量只在let命令所在的代码块内有效
一篇文章带你深入理解ES6let和const命令
       像上面例子,var声明的i是全局的,全局只有一个i,所以会输出i的最后的结果10,而let声明的i是仅在块级作用域中有效,所以输出的是6


不存在变量提升

       var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined。let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则便会报错。
一篇文章带你深入理解ES6let和const命令


暂时性死区

       只要块级作用域内存在let命令,它所声明的变量就“绑定”这个区域,不再受外部的影响
一篇文章带你深入理解ES6let和const命令
       在代码块内,使用let命令声明变量之前,这些变量都是不可用的
       暂时性死区的本质就是,只要进入当前作用域,所要使用的变量就已经存在,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量

不允许重复声明

       let不允许在相同作用域内重复声明同一个变量
一篇文章带你深入理解ES6let和const命令

块级作用域

什么是块级作用域

       任何一对花括号({和})中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域

为什么要有块级作用域

       ES5中只有函数作用域和全局作用域,没有块级作用域,这会导致一些场景不合适

变量非预期的重复覆盖

一篇文章带你深入理解ES6let和const命令
       因为判断里的tmp变量提升,所以覆盖掉了第一个tmp的值,导致第一个输出是undefined

用于循环计数的变量泄露为全局变量

一篇文章带你深入理解ES6let和const命令
       很多情况下,像这样的i,开发者只是定义用来控制循环,循环结束后却并没有消失,而是泄露为了全局的变量

ES6的块级作用域

       之前ES5中我们需要实现类似块级作用域的效果是使用立即执行函数
       ES6中,let实际上为js新增了块级作用域,使得立即执行函数不再必要了。

const命令

       const声明一个只读的常量,一旦声明,常量的值就不能改变,因为const声明的变量不得改变值。这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。
一篇文章带你深入理解ES6let和const命令
       const的作用域与let命令相同:只在声明所在的块级作用域内有效,const命令声明的常量也不会提升,同样存在暂时性死区,只能在声明后使用。使用const声明常量也与let一样,不可重复声明。

栈内存和堆内存

       为什么这里突然要介绍栈内存和堆内存呢,这和后面将要介绍的const命令的本质有关。
       javaScript中的变量分为基本类型和引用类型。
       基本类型是保存在栈内存中的简单数据段,它们的值都有固定的大小,保存在栈空间,通过按值访问
       引用类型是保存在堆内存中的对象,值大小不固定,栈内存中存放的该对象的访问地址指向堆内存中的对象,js不允许直接访问堆内存中的位置

const的本质

       const实际上保证的并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。但对于复合类型的数据而言,变量指向的内存地址保存的只是一个指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,这完全不能控制。因此,将一个对象声明为常量时必须非常小心。也就是说对象常量不可变的只是这个地址,即不能把foo指向另一个地址,但对象本身是可变的,依然可以为其添加新属性
一篇文章带你深入理解ES6let和const命令
       如果真的想将对象冻结,应该使用Object.freeze方法

       小伙伴们今天的学习就到这里了,如果觉得本文对你有帮助的话,欢迎转发,评论,收藏,点赞!!!
       每天学习进步一点点,就是领先的开始。如果想继续提高,欢迎关注我,或者关注公众号”祯民讲前端“。大量前端技术文章,面试资料,技巧等助你更进一步!
一篇文章带你深入理解ES6let和const命令