var、let、const声明的区别
前言
学习JavaScript高级程序设计中的var、const 和 let声明变量。下面详细介绍下3种声明的区别,最后通过表格整理了3者的区别方便记忆。
一、var声明
1.var作用域
使用var定义的变量会成为包含它的函数的局部变量,使用var在test()函数中定义一个变量,变量在函数外退出随即被销毁:
需要注意的是,在test()函数内部省略var,可以创建一个全局变量,只要调用过test(),这个变量就会被定义,并在函数外部访问到:
2.var声明提升
使用var时,关键字声明的变量会自动提升到函数作用域顶部,下面的代码不会报错:
不报错的原因是ECMAScript运行时把上述等价成:
同时,反复使用var声明一个变量也没有问题:
二、let声明
let与var最明显的区别是,let声明的范围是块作用域,而var声明范围是函数作用域。
if (true) {
var name = '老八';
console.log(name); // 老八
}
console.log(name); // 老八
if (true) {
let age = 26;
console.log(age); // 26
}
console.log(age); // ReferenceError: age 没有定义
age变量不能在if块外部使用,因为let作用域仅限于该块内部。块作用域是函数作用域的子集。
不同于var,let不允许同一块作用域出现冗余声明:
let age;
let age; // SyntaxError;标识符 age 已经声明过了
用于变量声明的标识符及其所在的块作用域,因此嵌套使用相同的标识符不会报错,而这是因为同一个块中没有重复声明:
var name = '老八';
console.log(name); // '老八'
if (true) {
var name = '丽丽';
console.log(name); // '丽丽'
}
let age = 30;
console.log(age); // 30
if (true) {
let age = 26;
console.log(age); // 26
}
1.暂时性死区
在 let 声明之前的执行瞬间被称为“暂时性死区”(temporal dead zone),在此阶段引用任何后面才声明的变量都会抛出 ReferenceError。let 声明的变量不会在作用域中被提升:
console.log(age); // ReferenceError:age 没有定义
let age = 26;
2.全局声明
与 var 关键字不同,使用 let 在全局作用域中声明的变量不会成为 window 对象的属性(var 声明的变量则会)
var name = '老八';
console.log(window.name); // '老八'
let age = 26;
console.log(window.age); // undefined
3.条件声音
在使用 var 声明变量时,由于声明会被提升,JavaScript 引擎会自动将多余的声明在作用域顶部合并为一个声明。因为 let 的作用域是块,所以不可能检查前面是否已经使用 let 声明过同名变量,同时也就不可能在没有声明的情况下声明它。
<script>
var name = '老八';
let age = 26;
</script>
<script>
var name = '丽丽';
// 这里没问题,因为可以被作为一个提升声明来处理
// 不需要检查之前是否声明过同名变量
let age = 36;
// 如果 age 之前声明过,这里会报错
</script>
4.for循环中使用let
使用var,for 循环定义的迭代变量会渗透到循环体外部:
for (var i = 0; i < 5; ++i) {
// 循环
}
console.log(i); // 5
使用let后,迭代变量的作用域仅限于 for 循环块内部:
for (let i = 0; i < 5; ++i) {
// 循环
}
console.log(i); // ReferenceError: i 没有定义
三、const声明
const 的行为与 let 基本相同,唯一一个重要的区别是用它声明变量时必须同时初始化变量,且尝试修改 const 声明的变量会导致运行时错误(const 声明的作用域也是块)。
常量赋值错误:
const age = 26;
age = 36;
重复声明错误:
const name = '老八';
const name = '丽丽'; // SyntaxError
const的块作用域:
const name = '老八';
if (true) {
const name = '丽丽';
}
console.log(name); // 老八
const 声明的限制只适用于它指向的变量的引用。换句话说,如果 const 变量引用的是一个对象,那么修改这个对象内部的属性并不违反 const 的限制。
const person = {};
person.name = '丽丽'; // ok
虽然 const 变量跟 let 变量很相似,但是不能用 const 来声明迭代变量(因为迭代变量会自增)
for (const i = 0; i < 10; ++i) {} // TypeError:给常量赋值
总结
JavaScript高级程序设计中给的建议是不使用 var、优先使用 const ,let 次之。
var、const 和 let声明区别表格
范围 | 变量提升 | 不可更改 | 是否可重复声明 | ES范围 | |
---|---|---|---|---|---|
var | 函数作用域 | 是 | 否 | 是 | 全部 |
let | 块作用域 | 否 | 否 | 否 | ES6 |
const | 块作用域 | 否 | 是 | 否 | ES6 |