var、let、const
var
- 函数作用域,作用域是全局或者整个函数快的
- 可重复声明
- 全局变量声明的 var 相当于挂载到 window
javascript
var a = 112;
window.a; // 112
- 变量提升
javascript
var a = 99; // 全局变量a
f(); // f是函数,虽然定义在调用的后面,但是函数声明会提升到作用域的顶部。
console.log(a); // a=>99, 此时是全局变量的a
function f() {
console.log(a); // 当前的a变量是下面变量a声明提升后,默认值undefined
var a = 10;
console.log(a); // a => 10
}
javascript
/**
* 因为变量提升,可以理解全局只有一个 y 变量,每次循环是改变 y 的值,
* 所以异步输出的都是最后一次执行的 y 的值
*/
for (var y = 0; y < 4; y++) {
setTimeout(function () {
console.log(y); // 4 4 4 4
}, 1000);
console.log('var', y); // 变量正常输出
}
console.log('yyyy', y); // 由于var可使变量提升,所以打印出的值为for循环中最后输出的值 yyyy 4
let
- 块级作用域
- 不能重复声明
- let 声明的变量在执行上下文创建阶段只会被创建,不会被初始化,因此对于执行阶段来说,如果在定义前使用则会报错,相当于使用了未被初始化的变量
javascript
for (let x = 0; x < 4; x++) {
console.log('let', x); // 变量正常输出
}
console.log('let', x); // 报错,提示x没有被定义
const
- 常量就是一旦定义完就不能修改的值
- 常量定义必须初始化值,如果不初始化值就会报错。
- 块级作用域
- 不能重复声明
javascript
const a = "111"
const b; // 报错 常量未初始化
暂时性死区
在代码块内,使用 let
const
命令声明变量之前,该变量都是不可用的。这在语法上,称为 暂时性死区
javascript
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
用 var 实现 let
使用匿名函数创建一个作用域,将变量保存起来
javascript
for (var y = 0; y < 4; y++) {
(function (arg) {
setTimeout(function () {
console.log('var => let: ', arg); // 4 4 4 4
}, 1000);
})(y);
}
总结
var 的特点
- 在全局上定义时,会被挂在
window
上 - 变量提升
- 可以重复声明
let、const
- 解决了污染全局命名空间的问题
- 与变量提升不同,会存在暂时性死区
- 无法重复声明
- 增加了块级作用域