# 经典整体
- let、const、var 的区别?什么是块级作用域?如何使用?
答案如下。
# 声明变量关键字
在 JavaScript 中有 3 中声明变量的方式:
- var
- let
- const
最初声明变量的关键字就是 var ,但是为了解决作用域问题,所以新增了 let 和 const 的声明方式。
# 什么是作用域
ES5 中的作用域有:全局作用域、函数作用域。
ES6 中新增了块级作用域,块级作用域有 {} 包括, if语句 和 for语句 里面的 {} 也属于块级作用域。
更多内容在 《作用域和作用域链》文章中。
# var 关键字
- 没有块级作用域的概念
| { |
| var a = 1; |
| } |
| console.log(a); |
- 有全局作用域、函数作用域的概念
| var a = 1; |
| function checkscope(){ |
| var b = 2; |
| console.log(a); |
| console.log(b); |
| } |
| checkscope(); |
| console.log(b); |
- 不初始化的值默认是
undefined
- 存在变量提升
变量提升 就是将变量的声明部分提升到当前作用域的最顶端。
| console.log(a); |
| var a = 1; |
| |
| checkscope(); |
| function checkscope() { |
| |
| console.log(a); |
| var a; |
| } |
- 全局作用用 var 声明的变量将会挂载到 window 对象下
| var a = 1; |
| console.log(a); |
| console.log(window.a); |
| console.log(this.a); |
- 统一作用域中允许重复声明
| var a = 1; |
| var a = 2; |
| console.log(a); |
| |
| checkscope(); |
| function checkscope(){ |
| var b = 1; |
| var b = 2; |
| console.log(b); |
| } |
# let 关键字
- 具有块级作用的概念
| { |
| let a = 1; |
| } |
| console.log(a); |
- 不存在变量提升
| console.log(a); |
| let a = 1; |
- 暂时性死区
| { |
| console.log(a); |
| let a = 1; |
| } |
| |
| if (true){ |
| |
| console.log(a); |
| |
| let a; |
| console.log(a); |
| |
| a = 2; |
| console.log(a); |
| } |
在声明变量 a 之前的区域被称为暂时性死区(TDZ)。这个区域是指从当前作用域开始,到变量实际声明的位置之间的部分
ES6 规定, let、const 命令会使区块形成封闭作用域。若在声明之前使用变量,就会报错。
总之,在代码块内,使用 let、const 命令声明变量之前,该变量都是不可用的。
这种情况在语法上被成为” 暂时性死区 “,简称: TDZ 。
暂时性锁区的原因是没有变量提升
- 不初始化的值默认是
undefined
- 同一块级作用域中不允许重复声明
| { |
| let a; |
| var a; |
| } |
| { |
| var a; |
| let a; |
| } |
| { |
| let a; |
| let a; |
| } |
# const 关键字
- 必须立即初始化,初始化后不能赋值
- 常量的值不能改变
const 并不是变量的值不得改动,而是变量指向的内存地址所保存的数据不得改动。
# 总结
- 没有块级作用域概念
- 有全局作用域,函数作用域的概念
- 不初始化时,默认值为:undefined
- 存在变量提升
- 全局作用域 var 声明的变量挂载到 window 对象下
- 同一作用域中允许重复声明
- 有块级作用域的概念
- 不存在变量提升
- 暂时性锁区
- 不会像 var 成为全局对象的属性。
- 同一块级作用域中不允许重复声明
- 与 let 特性一样,但是有两个差别
- 差别 1:必须立即初始化,不能留到以后赋值
- 差别 2:常量的值不能改变
过去无法挽回,未来可以改变,有的人成日殚精竭虑,却掀不起什么风浪,有的人却因一念之差,让世界天翻地覆,这就是命运权重。