js语言基础
一、变量
- let: 块级作用域
- var: 函数作用域、变量提升
- const: 块级作用域,定义常量
1.1 let声明
在let出现之前,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没有定义
在使用var的时候,最常见的问题就是对迭代变量的奇特声明和修改:
for (var i = 0; i < 5; ++i) {
setTimeout(() => console.log(i), 0)
}
// 你可能以为会输出0、1、2、3、4
// 实际上会输出5、5、5、5、5
之所以会这样,是因为在退出循环时,迭代变量保存的是导致循环退出的值:5。在之后执行超时逻辑时,所有的i都是同一个变量,因而输出的都是同一个最终值。

而在使用let声明迭代变量时,JavaScript引擎在后台会为每个迭代循环声明一个新的迭代变量。每个setTimeout引用的都是不同的变量实例,所以console.log输出的是我们期望的值,也就是循环执行过程中每个迭代变量的值。
for (let i = 0; i < 5; ++i) {
setTimeout(() => console.log(i), 0)
}

// 会输出0、1、2、3、4

这种每次迭代声明一个独立变量实例的行为适用于所有风格的for循环,包括for-in和for-of循环。

1.2 const声明
const的行为与let基本相同,唯一一个重要的区别是用它声明变量时必须同时初始化变量,且尝试修改const声明的变量会导致运行时错误。
const age = 26;

age = 36; // TypeError:给常量赋值

// const也不允许重复声明

const name = 'Matt';

const name = 'Nicholas'; // SyntaxError

// const声明的作用域也是块

const name = 'Matt';

if (true) {

const name = 'Nicholas';

}

console.log(name); // Matt
const声明的限制只适用于它指向的变量的引用。换句话说,如果const变量引用的是一个对象,那么修改这个对象内部的属性并不违反const的限制。const person = {};
person.name = 'Matt'; // ok
JavaScript引擎会为for循环中的let声明分别创建独立的变量实例,虽然const变量跟let变量很相似,但是不能用const来声明迭代变量(因为迭代变量会自增):for (const i = 0; i < 10; ++i) {} // TypeError:给常量赋值

浙公网安备 33010602011771号