JavaScript中,var、let和const的区别
ES6建议不再使用var
定义变量,而使用let
定义变量,const
定义常量。
无论是
let
还是const
,它们均解决了JS中长久以来的变量定义的问题。
咱们先聊聊var
和let
的区别。
一、变量具有块级作用域,在代码块之外不可使用
使用var
定义变量时,无论其实际声明位置在何处,都会被视为声明于所在函数的顶部 (如果声明不在任意函数内,则视为在全局作用域的顶部),使用if或者for等循环定义的变量,变量同样会被提升到if或for所在的函数顶部。
![](https://img.haomeiwen.com/i10916621/610ed2fba92ca775.png)
使用let
定义变量时,该变量只能在当前块级作用域里使用,在外部访问会显示未定义
块级作用域(又被称为词法作用域)会在以下两种情况被创建:
- 在一个函数内部
- 在一个代码块(由一对花括号包裹,比如if、for、switch、while)内部
![](https://img.haomeiwen.com/i10916621/07cd294c19dbc3f9.png)
接下来我们看看在循环中使用的情况
如果我们在for循环中用var
定义变量,在延迟后输出i
,可以看到全部输出的都是3,这是由于i
变量的定义被提升出去了,左边的代码等价于右边的代码
![](https://img.haomeiwen.com/i10916621/82e06ea4231bd24d.png)
而在过去我们要解决这个问题只能通过 IIFE 来强制改变作用域去解决这个问题
![](https://img.haomeiwen.com/i10916621/3799d24a02770192.png)
如果在for循环中使用let
定义变量,变量所在的作用域是在循环体这个代码块内,因此在循环外就不能使用了。另外,for循环会对该变量做特殊处理,让每次循环使用的都是一个独立的循环变量。
![](https://img.haomeiwen.com/i10916621/0240c25f317869d9.png)
二、变量的提升问题
用var
定义的变量先赋值再声明是没有任何问题的,因为里面会有变量提升的情况。
![](https://img.haomeiwen.com/i10916621/78dbd748e9cf0454.png)
而用let
定义的变量不会被提升,这里有个暂时性死区的概念
暂时性死区
使用
let
或const
声明的变量,在到达声明处之前都是无法访问的,会被放置在JS社区称为暂时性死区( temporal dead zone ,TDZ )的区域内,试图访问会导致一个引用错误。虽然该名称并未在 ECMAScript 规范中被明确命名,但经常被用于描述
let
或const
声明的变量为何在声明处之前无法被访问。
下面放一个先赋值再声明会直接报 Cannot access 'a' before initialization 的错误的例子
![](https://img.haomeiwen.com/i10916621/8887c526e3491a7c.png)
三、全局定义的变量不再作为属性添加到全局对象中
在全局使用var
定义的变量会被挂载到全局也就是window对象中
![](https://img.haomeiwen.com/i10916621/d80aebbb72700976.png)
而使用let
定义的变量并不会被挂载到全局对象中
![](https://img.haomeiwen.com/i10916621/fd5fe688a959b478.png)
四、不可重复定义同名变量
var
在重复定义同名变量的时候并不会报错,最终打印会是最后一个所赋的值
![](https://img.haomeiwen.com/i10916621/036bd3577dbabd20.png)
let
重复定义同名变量会直接报 Identifier 'a' has already been declared 的错误
![](https://img.haomeiwen.com/i10916621/b49f7d4ada88f6f1.png)
下面来聊聊const
的使用
const
和let
同样具有块级作用域,且声明不会被提升的特点。- 使用
const
定义变量时,必须初始化
在过去只有var
一个关键字,没有办法清晰的表明这个变量是否需要修改,而新增了let
和const
关键字后,可以使用let
来声明可以被修改的变量,使用const
来声明不会被修改的变量,而使用const
声明的变量会被认为是常量( constant ),这样语义上会更加清晰。
如果我们尝试修改const
定义的变量,会报Assignment to constant variable错误。
![](https://img.haomeiwen.com/i10916621/45c4fbf9b20142ce.png)
由于不可以被更改的特性,那么我们用const
定义变量的时候就必须初始化,不然会报Missing initializer in const declaration的错误,而使用var
和let
的话,可以先声明后面需要的时候再赋值。
![](https://img.haomeiwen.com/i10916621/ee4833dc0843ab73.png)