推荐答案
let 和 const 是 ES6 引入的用于声明变量的关键字,它们与 var 的主要区别在于:
作用域:
var声明的变量具有函数作用域(function scope),即在函数内部声明的变量在整个函数内部都可用,如果在函数外部声明则为全局作用域。let和const声明的变量具有块级作用域(block scope),即变量只在声明它们的代码块(例如if语句、for循环、{}包裹的代码)内部可用。
变量提升(Hoisting):
var声明的变量存在变量提升,即在声明语句之前就可以访问,只是值为undefined。let和const声明的变量不存在变量提升,如果在声明语句之前访问,会抛出ReferenceError错误,形成“暂时性死区”(Temporal Dead Zone,TDZ)。
重复声明:
var允许在同一作用域内重复声明同一个变量,后面的声明会覆盖前面的。let和const在同一作用域内不允许重复声明同一个变量,会抛出SyntaxError错误。
变量修改:
var和let声明的变量的值可以被修改。const声明的变量必须在声明时初始化,并且其值不能被重新赋值。但是,如果const声明的是一个对象或数组,那么对象或数组的内容是可以被修改的。
特性 var let const 作用域 函数作用域 块级作用域 块级作用域 变量提升 有 无(TDZ) 无(TDZ) 重复声明 允许 不允许 不允许 值修改 允许 允许 不允许(基本类型),允许(引用类型)
本题详细解读
1. 作用域差异:函数作用域 vs. 块级作用域
var 的函数作用域:
var 声明的变量在函数内定义时,其作用域限定在整个函数内部。如果在函数外定义,则为全局作用域。这意味着,即使在函数内部的某个代码块中声明 var 变量,它在该函数的所有位置都是可以被访问的。这会导致一些潜在的问题,比如变量覆盖。
function exampleVar() {
if (true) {
var x = 10; // x 在整个函数内部都是可访问的
}
console.log(x); // 输出 10
}
exampleVar();
console.log(typeof x) //输出 "undefined" x的作用域只在函数内部let 和 const 的块级作用域:
let 和 const 声明的变量的作用域被限定在最近的代码块内。这包括 if,for, while 循环和任何由花括号 {} 包裹的代码块。这样的设计可以更好地控制变量的可见性,避免变量冲突,使代码更清晰。
// www.javascriptcn.com code example
function exampleLetConst() {
if (true) {
let y = 20;
const z = 30;
console.log(y); // 输出 20
console.log(z) // 输出 30
}
//console.log(y); // 报错:ReferenceError: y is not defined
//console.log(z); // 报错:ReferenceError: z is not defined
}
exampleLetConst();2. 变量提升(Hoisting)
var 的变量提升:
var 声明的变量会在代码执行前被 “提升” 到当前作用域的顶部。这意味着你可以在声明变量之前使用它,但其值会是 undefined,直到执行到声明语句时才会被赋值。
console.log(myVar); // 输出 undefined var myVar = 40; console.log(myVar); // 输出 40
let 和 const 的暂时性死区:
let 和 const 声明的变量不会被提升,如果在声明之前访问,会抛出一个 ReferenceError,表示该变量尚未被声明。这个区域被称为 “暂时性死区”(TDZ)。
//console.log(myLet); // 报错:ReferenceError: Cannot access 'myLet' before initialization let myLet = 50; console.log(myLet); // 输出 50 //console.log(myConst); // 报错:ReferenceError: Cannot access 'myConst' before initialization const myConst = 60; console.log(myConst) //输出 60
3. 重复声明
var 允许重复声明:
var 允许在同一个作用域内多次声明同一个变量,后面的声明会覆盖前面的声明,这可能会导致意想不到的错误。
var a = 1; var a = 2; console.log(a); // 输出 2
let 和 const 不允许重复声明:
let 和 const 在同一作用域内不允许重复声明同一个变量,这样做会抛出 SyntaxError,这有助于防止程序中出现不必要的错误。
let b = 1; //let b = 2; // 报错:SyntaxError: Identifier 'b' has already been declared const c = 3; //const c = 4; // 报错:SyntaxError: Identifier 'c' has already been declared
4. 变量修改
var 和 let 允许修改:
var 和 let 声明的变量的值在声明后可以被多次修改。
var d = 1; d = 2; console.log(d); // 输出 2 let e = 3; e = 4; console.log(e); // 输出 4
const 不允许修改:
const 声明的变量必须在声明时初始化,并且其值不能被重新赋值。但是,如果 const 声明的是一个对象或数组,那么对象或数组的内容是可以被修改的。这是因为 const 保证的是变量指向的内存地址不发生改变,而不是保证对象或数组内容不变。
// www.javascriptcn.com code example
const f = 5;
//f = 6; // 报错:TypeError: Assignment to constant variable.
const obj = { prop: 1 };
obj.prop = 2; // 可以修改对象属性
console.log(obj.prop); // 输出 2
const arr = [1, 2];
arr.push(3); // 可以修改数组内容
console.log(arr); // 输出 [1, 2, 3]
//arr = [1,2,3,4] //报错TypeError: Assignment to constant variable.