变量 | var let const区别及应用

1. var

(1)var声明作用域

使用var操作符定义的变量会成为包含它的函数的局部变量,换句话说var声明的变量的作用域是它当前的执行上下文及其闭包

局部变量说明:在函数调用完之后会被销毁

1
2
3
4
5
function test() {
var message = 'hi'; // message是test函数的局部变量
}
test();
console.log(message); // 报错

(2)var声明提升

var声明的变量会自动提升到作用域顶部

1
2
console.log(message); // undefined
var message = 'hi';

2. let

(1)块级作用域

let声明的范围是块级作用域,var声明的范围是函数作用域

1
2
3
4
5
6
7
8
9
10
11
12
if (true) {
var name = 'Matt';
console.log(name); // Matt
};
console.log(name); // Matt


if (true) {
let age = 26;
console.log(age); // 26
};
console.log(age); // ReferenceError: age没有定义

(2)不允许重复声明

let不允许在同一个块作用域中出现冗余声明,注意是同一块级作用域!

1
2
3
4
5
var name;
var name;

let age;
let age; // SyntaxError: 标识符age已经声明过了

(3)暂时性死区

let声明的变量不会在作用域中提升

暂时性死区:在let声明之前不允许任何方式来引用未声明变量,会抛出错误ReferenceError

1
2
3
4
5
6
7
// name会被提升
console.log(name); // undefined
var name = 'Matt';

// age不会被提升
console.log(age); // ReferenceError:age没有定义
let age = 16;

(4)全局声明

let声明的变量不会成为window对象的属性,而var会

1
2
3
4
5
var name = 'Matt';
console.log(windew.name); // Matt

var age = 16;
console.log(window.age); // undefined

3. const

const具有let的以上行为

(1)声明即初始化

const声明变量时必须同时初始化

(2)声明后不允许改变

const声明后为常量,不允许改变

const声明的限制只适用于它指向的变量的引用

1
2
const person = {};
person.name = 'Jack'; // 不会报错!

4. 面试题

(1)for循环中的let声明

  • 循环泄漏问题

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    for (var i = 0; i<5; i++) {
    // 循环逻辑
    };
    console.log(i); // 5


    for (let i = 0; i<5; i++) {
    // 循环逻辑
    };
    console.log(i); // i is undefined
  • 迭代变量的奇特声明和修改

    1
    2
    3
    4
    5
    6
    7
    8
    9
    for (var i = 0; i < 5; i++) {
    setTimeout(() => console.log(i), 0);
    };
    // 5 5 5 5 5

    for (let i = 0; i < 5; i++) {
    setTimeout(() => console.log(i), 0);
    };
    // 0 1 2 3 4