乐趣区

JS中let和var的区别

1. 定义变量

声明语法
var upperA = ‘A’;
let upperB = ‘B’;
const upperC = ‘C’;

只声明不初始化的结果,【const 定义的常量不可以修改,而且必须初始化。】
// var 声明变量
var upperA;
console.log(‘ 打印大写的 A:%s’, upperA);
// 结果:打印大写的 A:undefined

// let 声明变量
var upperB;
console.log(‘ 打印大写的 B:%s’, upperB);
// 结果:打印大写的 B:undefined

// const 声明常量
const upperC;
console.log(‘ 打印大写的 C:%s’, upperC);
// 错误:SyntaxError: Missing initializer in const declaration

声明后值是否可修改,【const 定义的常量不可以修改,而且必须初始化。】
// var 声明变量初始化并修改值
var upperA = ‘A’;
console.log(‘ 打印 upperA:%s’, upperA);
// 结果:打印 upperA:A
upperA = ‘LetterA’;
console.log(‘ 打印 upperA:%s’, upperA);
// 结果:打印 upperA:LetterA

// let 声明变量初始化并修改值
var upperB = ‘B’;
console.log(‘ 打印大写的 B:%s’, upperB);
// 结果:打印 upperB:B
upperB = ‘LetterB’;
console.log(‘ 打印大写的 B:%s’, upperB);
// 结果:打印 upperB:LetterB

// const 声明常量初始化并修改值
const upperC = ‘C’;
console.log(‘ 打印 upperC:%s’, upperC);
// 结果:打印 upperC:C
upperC = ‘LetterC’;
console.log(‘ 打印 upperC:%s’, upperC);
// 错误:TypeError: Assignment to constant variable.

2. 变量提升

浏览器在运行代码之前会进行预解析,首先解析函数声明,定义变量,解析完之后再对函数、变量进行运行、赋值等不论 var 声明的变量处于当前作用域的第几行,都会提升到作用域的头部。var 声明的变量会被提升到作用域的顶部并初始化为 undefined,而 let 声明的变量不会被提升到作用域的顶部。
console.log(‘ 打印 upperA:%s’, upperA);
// 结果:打印 upperA:undefined
console.log(‘ 打印 upperB:%s’, upperB);
// 错误:ReferenceError: upperB is not defined
var upperA = ‘A’;
let upperB = ‘B’;

3. 是否允许重复声明同一个变量

** var 允许在相同作用域内,重复声明同一个变量,后面声明的变量会覆盖前面声明的变量。** let 不允许在相同作用域内,重复声明同一个变量。
var upperA = ‘A’;
let upperB = ‘B’;
// 重复声明
var upperA = ‘LetterA’;
let upperB = ‘LetterB’;
console.log(‘ 打印 upperA:%s’, upperA);
console.log(‘ 打印 upperB:%s’, upperB)
// 错误:SyntaxError: Identifier ‘upperB’ has already been declared

4. 作用域

在 ES6 之前,我们都是用 var 来声明变量,而且 JS 只有函数作用域和全局作用域,没有块级作用域,所以 {} 限定不了 var 声明变量的访问范围。
// ———- 例如:———-
{
var upperA = ‘A’;
}
console.log(‘ 打印 upperA:%s’, upperA);
# 结果:打印 upperA:A

// ———- ES6 新增的 let,可以声明块级作用域的变量。———-
{
let upperB = ‘B’;
}
console.log(‘ 打印 upperB:%s’, upperB);
// 错误:ReferenceError: upperB is not defined

5. let 配合 for 循环的独特应用

let 非常适合用于 for 循环内部的块级作用域。** JS 中的 for 循环体比较特殊,每次执行都是一个全新的独立的块作用域,用 let 声明的变量传入到 for 循环体的作用域后,不会发生改变,不受外界的影响。
// ———- 看一个常见的面试题目:———-
for (var i = 0; i <10; i++) {
setTimeout(function() {// 同步注册回调函数到 异步的 宏任务队列。
console.log(i); // 执行此代码时,同步代码 for 循环已经执行完成
}, 0);
}
// 输出结果:10 共 10 个
// 这里面的知识点:JS 的事件循环机制,setTimeout 的机制等

// ———- 如果把 var 改成 let 声明:———-
// i 虽然在全局作用域声明,但是在 for 循环体局部作用域中使用的时候,变量会被固定,不受外界干扰。
for (let i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i); // i 是循环体内局部作用域,不受外界影响。
}, 0);
}
// 输出结果:0 1 2 3 4 5 6 7 8 9

退出移动版