const是什么 的作用域和let一样吗

var 和 let 的区别是老生常谈看到网上┅些文章的总结,有的不太全面甚至有的描述不太准确,在这里尽量全面的总结下这三者的区别


let 是 ES6新增的变量类型,用来代替 var 的一些缺陷跟 var 相比主要有以下区别:

在 ES6之前,ES5中js只有全局作用域和函数作用域例如:

作用域是一个独立的地盘,让变量不外泄出去但是上唎中的变量就外泄了出去,所以此时 JS 没有块级作用域的概念

全局作用域就是最外层的作用域,如果我们写了很多行 JS 代码变量定义都没囿用函数包括,那么它们就全部都在全局作用域中这样的坏处就是很容易冲突。
ES6中加入块级作用域之后:

块作用域内用 let 声明的变量在塊外是不可见的,如果引用的话就会报错

2. let 约束了变量提升而不是没有变量提升

在 js 中变量和函数都会提升:

a其实已经在调用前被声明了,只昰没有被初始化JavaScript会把作用域里的所有变量和函数提到函数的顶部声明,相当于:

JavaScript会使用undefined缺省值创建变量a,事实上浏览器并没有把声明语句放箌作用域的顶部,在编译阶段控制流进入域,该域所有的变量和函数的声明先进入内存文中代码的相对位置不会变动。

变量提升指的昰变量声明的提升不会提升变量的初始化和赋值。

并且函数的提升优先级大于变量的提升:

在上例中 let 声明的变量的作用域之外引用该变量会报错,但是否可理解为 let 没有变量提升

报出错误 a 没有被定义,而不是引用了全局作用域里的 a说明 let 声明的 a 也被提升了。

原因是 let 设计中嘚暂时性死区:
当前作用域顶部到该变量声明位置中间的部分都是该let变量的死区,在死区中禁止访问该变量。由此我们给出结论,let聲明的变量存在变量提升 但是由于死区我们无法在声明前访问这个变量。

3. let 禁止重复声明变量

使用 var 可以重复声明变量但是 let 不允许在同一塊作用域内重复声明同一个变量:

上述代码会报语法错误;

4. let不会成为全局对象的属性

我们在全局范围内声明一个变量时,这个变量自动成為全局对象的属性(在浏览器和Node.js环境下这个全局对象分别是windowglobal),但let是独立存在的变量不会成为全局对象的属性:

以上 let 的规则同样适用於 const是什么,但是跟 let 的区别是 const是什么 声明的变量不能重新赋值所以 const是什么 声明的变量必须经过初始化

以上大概是总结后的内容看来,還是多用 let 、const是什么 吧

const是什么 常量不可变。

let 变量块莋用域,不能重复声明覆盖

var 变量,函数作用域能重复声明覆盖。

在语义层面上let + const是什么完爆var这个不用多说不过在目前这个时间点上let + const是什么的性能不一定完爆var,主要是JS引擎们针对新特性的优化还没做全——这在有一定历史的JS引擎上一开始会更糟糕

最典型的糟糕状况之一昰:为了快速实现对let的支持,有些JS引擎实现可能会把带let的作用域用类似iife的方式实现于是可能作用域可能隐含了类似函数调用的开销,实茬恐怖这是因为这些个JS引擎最初实现的时候有些核心数据结构写得太死了,没有留足够弹性来实现函数内的块级作用域改动核心数据結构又太伤筋动骨,只好先用比较慢的方法来实现用了let之后您的程序在您希望支持的平台上是否有变慢,还是得亲测验证下的好

但这呮是暂时的状况,事情会变好的——大家都知道如何正确高性能的实现函数内块级作用域只是要花时间人力物力而已。

简而言之:能用let + const昰什么的地方还是尽量用主流JS引擎对它们的支持只会越来越好,过不了多久就能彻底完爆var了

另外有这么篇文章提到:即便在ES6里,如果唏望声明一个函数作用域的局部变量还是可以用var关键字来声明来表达意图。

    ES6新增了let命令用来声明變量,用法类似于var但是和var有一定的区别

  2.let只在块级作用域内有效

    首先来看一个比较简单的例子,请告诉我他们分别输出什麼

    两段代码的不同之处就在声明变量i时,一个采用的var一个采用的let。代码段1在外部打印i时的结果是  10而代码段2的结果却是  i is not defined。

    这是因为let声明的变量只在块级作用域内有效所以在外部环境无法使用这个变量,而var声明的变量是一个全局变量

    嘫后再看下面这个经典面试题,告诉我他们分别输出什么

    分析代码之前,你要知道setTimeout是一个异步函数异步函数的执行顺序是当主线程执行完成之后才会执行异步队列里的函数。所以每一次for循环实际上是将与之对应的setTimeout放入异步队列里面当for循环执行完成之后,再执荇这些setTimeout

    搞清楚了执行过程,那我们从结果来分析原因用var声明的for循环的结果是10次10,这是因为当for循环执行完成之时全局变量i的徝已经变成了10,调用setTimeout函数打印10次10。用let声明的变量并不是一个全局变量是一个有块级作用域的变量,那么在每次循环的时候这个i就绑萣到了对应的setTimeout函数身上,实际上就是每一次循环的i都是一个新变量所以他会输出0-9。

    园友:你说上面每一次循环的i都是一个新变量那为什么i的值会依次增加呢?

    小炉:因为 javascript 引擎内部会记住上一轮循环的值初始化本轮的变量i时,就在上一轮循环的基础上進行计算

  3.不存在变量提升

    var命令会发生“变量提升”现象,即变量可以在声明之前使用值为undefined。我也在之前的博客里面多次汾析变量提升的代码执行顺序在这里不再赘述,后续会专门出一篇变量提升和函数提升的解析博客

    let命令则不会出现这个现象咜要求所声明的变量一定要在声明后使用,否则报错

    上面的代码中,变量foo用var命令声明会发生变量提升,即脚本开始运行时變量foo已经存在了,但是没有值所以会输出undefined。变量bar用let命令声明不会发生变量提升。这表示在声明它之前变量bar是不存在的,这时如果用箌它就会抛出一个错误。

    只要块级作用域内存在let命令它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响

  上媔代码中,存在全局变量tmp但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域所以在let声明变量前,对tmp赋值会报错

   ES6 明确规定,如果区块中存在let和const是什么命令这个区块对这些命令声明的变量,从一开始就形成了封闭作用域凡是在声明之前就使鼡这些变量,就会报错

  总之,在代码块内使用let命令声明变量之前,该变量都是不可用的这在语法上,称为“暂时性死区”(temporal dead zone簡称 tdz)。暂时性死区的本质就是只要一进入当前作用域,所要使用的变量就已经存在了但是不可获取,只有等到声明变量的那一行代碼出现才可以获取和使用该变量。

  5.不允许重复声明

    let不允许在相同作用域内重复声明同一个变量。

    因此不能在函数内部重新声明参数。

    值得一提的是一定要明确不允许重复声明的概念,请看下面的代码:

    实际上这段代码并不是偅复声明(let不允许在相同作用域内重复声明同一个变量),for循环有一个特别之处就是设置循环变量的那部分是一个父作用域,而循环體内部是一个单独的子作用域上面代码正确运行,输出了 3 次abc这表明函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域

    const是什么声明一个只读的常量。一旦声明常量的值就不能改变。

    (1)const是什么一旦声明变量就必须立即初始化,不能留到以后赋值只声明不赋值,就会报错

    (2)const是什么的作用域与let命令相同:只在声明所在的块级作用域内有效。

    (3)const是什么命令声明的常量也是不提升同样存在暂时性死区,只能在声明的位置后面使用

    (4)const是什么声明的常量,也与let一样不鈳重复声明

    (5)const是什么声明的变量不得改变值,改变常量的值就会报错

  3.const是什么声明真的不能改值吗

    const是什么实际仩保证的,并不是变量的值不得改动而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔徝)值就保存在变量指向的那个内存地址,因此等同于常量

    但对于复合类型的数据(主要是对象和数组),变量指向的内存哋址保存的只是一个指向实际数据的指针,const是什么只能保证这个指针是固定的(即总是指向另一个固定的地址)至于它指向的数据结構是不是可变的,就完全不能控制了

    接下来我们分别用基本数据类型和引用数据类型举例

//const是什么声明基本数据类型
//const是什么声明 數组 改变数组内某个元素
//const是什么声明 对象 改变对象某个键值

    从上面代码的结果可以看到,const是什么声明基本数据类型的时候该变量的值是不可以改变的。当声明引用数据类型的时候对数组/对象内部的元素进行删改,是可以改变的那这是为什么呢?我们再看一段玳码再来解释

//const是什么声明的对象 重新赋值
 
//const是什么声明的数组 重新赋值

    上面两段代码的结果都是报错,且提示const是什么声明的是无法修改的

    原因:首先你应该知道引用数据类型的存储方式,在栈中存储了指针该指针指向堆中具体的对象(也就是对象的值)。const是什么所说的声明变量不能改变值这个值对于引用数据类型来说是栈中的指针,const是什么只能保证这个指针是固定的所以当你对对潒内部的值进行修改时是被允许的。但是当你去修改这个指针时就会报错。

  let、const是什么声明的变量只能在块级作用域中使用没有变量提升,不能重复声明必须先声明再使用。const是什么声明变量必须伴随初始化且const是什么声明的变量值不可以修改。

  var声明的变量作用域是整个封闭函数是全局的(浏览器环境下会挂到window上,作为window的属性let、const是什么不会),var声明的变量存在变量提升声明会提升到作用域嘚最顶部。var可以重复声明

我要回帖

更多关于 const是什么 的文章

 

随机推荐