开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情
前言
let const var有什么区别?什么是块级作用域?
基础概念
var、let、const是用来声明变量的三种方式,let和const是ES6推出的声明变量方式;ES6之前的作用域有:全局作用域、函数作用域,ES6新增了块级作用域,块级作用域由一对大括号{ }包裹。
区别
由于 let 和 const 特性相似,在文章结尾会对二者细节上的区别进行记录,这里只比较 let 和 var 的区别,
var没有块级作用域概念,let有
// Global Scope
{
// Block Scope
var a = 10;
let b = 20;
}
console.log(a); // 10
console.log(b); // ReferenceError: b is not defined
在Global Scope(全局作用域)中访问Block Scope(块级作用域)中var定义的变量a,输出结果为10,访问let定义的变量b则会报错:ReferenceError: b is not defined。
- 同一作用域中,
var允许重复声明,let则不行
//Global Scope
var a = 10;
var a = 20;
console.log(a); //20
let b = 30;
let b = 40;
console.log(b); //SyntaxError: Identifier 'b' has already been declared
- 全局作用域使用
var声明的变量会挂载到window对象上,let则不会
//Global Scope
var a = 10;
console.log(window.a); //10
let b = 20;
console.log(window.b); //undefined
var存在变量提升,let不存在变量提升
console.log(a); // undefined
var a = 'global a';
function localScope() {
console.log(a); // global a
console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 'local b';
}
localScope();
- 在
Global Scope中访问var关键字定义变量a,得到结果为undefined; - 在
Local Scope中访问var关键字定义变量a得到的结果也是Global a,说明Local Scope中读取变量是按照作用域的层级依次往上找的,即:Local Scope中没有定义变量a,则读取Global Scope中的变量a; - 在
Local Scope中访问let关键字定义的变量b,程序报错:ReferenceError: Cannot access 'b' before initialization。 注意:这里错误信息指的是,不能在初始化之前访问变量b,而不是b is not defined
let声明的变量存在暂时性死区(Temporal Dead Zone)
造成ReferenceError: Cannot access 'b' before initialization的原因是 let 声明的变量 b存在 暂时性死区。
什么是暂时性死区?
The variables are created when their containing Lexical Environment is instantiated but may not be accessed inany way until the variable’s LexicalBinding is evaluated. --- ES6标准第13章
即:当在新的作用域进行实例化时,在此作用域中用 let/const 声明的变量会先在作用域中被创建出来,但因此时还未进行词法绑定,所以是不能被访问的,如果访问就会抛出错误。因此,在程序运行流程进入作用域创建变量,到变量可以被访问之间的这一段时间,就称之为暂时死区。
简单来说就是,ES6规定了let 和 const 命令会使区块形成封闭的作用域。如果在声明前访问变量,就会报错。
const 关键字
const 关键字特性和 let 一致,区别在于:
- 声明变量时就必须赋值,且后续不可更改
- 后续不可更改指的是:变量指向的内存地址不可以修改
const a; // SyntaxError: Missing initializer in const declaration
const b = 10;
b = 5; // TypeError: Assignment to constant variable.
const c = {
d: 1,
e: 2
}
c.d = 3
console.log(c); // { d: 3, e: 2 }
总结
var关键字
- 没有块级作用域的概念,只有全局作用域、函数作用域的概念;
- 同一作用域中允许重复声明
- 全局作用域使用声明的变量会挂载到
window对象上 - 存在变量提升
let关键字
- 存在块级作用域的概念
- 同一作用域中不允许重复声明
- 不存在变量提升,且具有
暂时性死区
const关键字 和let差别:声明变量时必须赋值,且其指向的内存地址在后续不可更改