ES5 中只有两种声明变量的方法:var 命令和 function 命令。
ES6 中有六种声明变量的方法:除了 var 命令和 function 命令,还有 let 命令、const 命令、class 命令和 import 命令。
let 命令:
let 命令用来声明变量,用法和 var 类似。
// 声明变量:可以只声明一个
let a
// 声明变量:可以声明多个,用逗号隔开
let a, b
// 声明变量并初始化
let a = 10
let a = 10, b = 20
有块级作用域:
let 声明的变量,只在 let 命令所在的代码块内有效。
ES6 之前只有两种作用域:全局作用域和函数作用域。ES6 中又增加了块级作用域,通过 let、const、function、clsss 声明的变量都有块级作用域。
但是由于 JS 引擎担忧老旧代码的兼容性问题,因此对 function 声明的函数做了特殊处理,在块级作用域外仍然能够访问到,但是只能在代码块的后面访问,不能在前面访问。foo() // 无法访问,报错 { function foo() {} } foo() // 可以访问
{
let a = 10
var b = 1
}
console.log(a) // ReferenceError: a is not defined.
console.log(b) // 1
不允许重复声明:
let 不允许在同一个作用域内,重复声明同一个变量。
// 报错
function func() {
let a = 10
let a = 1
}
// 报错
function func() {
let a = 10
var a = 1
}
// 不报错
function func() {
var a = 10
var a = 1
}
不存在变量提升:
let 不存在变量提升,所声明的变量一定要在声明后使用,否则报错。
let、const 声明的变量在包含它们的词法环境被创建的时候,就被提前创建出来了,只是不能被访问,直到词法绑定被求值才能访问。
var 命令会发生变量提升现象,即变量可以在声明之前使用,值为 undefined。
console.log(foo) // 输出 undefined
var foo = 2
console.log(bar) // 报错 ReferenceError。bar 其实已经被提前创建出来了,只是不能被访问
let bar = 2
暂时性死区:
在 let 命令所在作用域的顶部一直到它所声明的变量完成之前的区域,就叫暂时性死区。在暂时性死区内,声明的变量不能被访问。
var tmp = 123
if (true) {
console.log(tmp) // ReferenceError。即使外部也有 tmp,但位于暂时性死区,tmp 不能被访问
let tmp = 'abc'
}
不属于顶层对象的属性:
let 声明的全局变量,不会被添加为顶层对象的属性。
let、const 声明的全局变量会被放到全局环境记录的变量环境记录里;而全局环境记录的对象环境记录才是 window。
var 命令声明的全局变量会被添加为顶层对象的属性。
var a = 1
window.a // 1
let b = 1
window.b // undefined
const 命令:
const 用来声明只读的常量,一旦声明,常量的值就不能改变,改变常量的值会报错。
const PI = 3.1415
console.log(PI) // 3.1415
PI = 3 // TypeError: Assignment to constant variable.
这意味着,const 一旦声明变量,就必须立即初始化,不能留到以后赋值。
const foo // SyntaxError: Missing initializer in const declaration
const 实例上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于基本类型的数据,值就保存在变量指向的那个内存地址,因此等同于常量。但对于引用类型的数据,变量指向的内存地址,保存的只是一个指向实际数据的指针,const 只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了。
const foo = {}
// 为 foo 添加一个属性,可以成功
foo.prop = 123;
console.log(foo.prop) // 123
// 将 foo 指向另一个对象,就会报错
foo = {} // TypeError: "foo" is read-only
const 有块级作用域;不允许重复声明;声明的常量不提升;存在暂时性死区;声明的常量不会被添加为顶层对象的属性。
本文详细介绍了ES6中新增的变量声明方式,包括let和const命令,以及它们与ES5中var命令的区别。探讨了块级作用域、变量提升、暂时性死区等概念,并对比了不同声明方式下变量的特性。
1758





