- let创建的变量是可以更改指针指向(可以重新赋值)。但const声明的变量是不允许改变指针的指向
在下面代码中,使用 let 声明了变量 num 并初始赋值为 10,之后可以对 num 重新赋值为 20,这体现了 let 创建的变量可以更改指针指向(重新赋值)。
// 使用 let 声明变量 num
let num = 10;
console.log(num); // 输出: 10
// 重新赋值
num = 20;
console.log(num); // 输出: 20
使用 const 声明变量并尝试重新赋值
// 使用 const 声明常量 PI
const PI = 3.14;
console.log(PI); // 输出: 3.14
// 尝试重新赋值,会报错
// PI = 3.1415; // 这里会抛出 TypeError 错误
// 对于引用类型,const 保证指针指向不变,但对象属性可以修改
const person = {
name: 'John',
age: 30
console.log(person); // 输出: { name: 'John', age: 30 }
// 修改对象属性
person.age = 31;
console.log(person); // 输出: { name: 'John', age: 31 }
// 尝试改变指针指向,会报错
// person = { name: 'Jane', age: 25 }; // 这里会抛出 TypeError 错误
2.在变量声明时,var 和 let 可以不用设置初始值。而const声明变量必须设置初始值。写一个例子
使用 var 声明变量不设置初始值
// 使用 var 声明变量 num,但不设置初始值
var num;
console.log(num); // 输出: undefined
// 后续可以为其赋值
num = 10;
console.log(num); // 输出: 10
使用 let 声明变量不设置初始值
// 使用 let 声明变量 str,但不设置初始值
let str;
console.log(str); // 输出: undefined
// 后续可以为其赋值
str = "Hello";
console.log(str); // 输出: Hello
使用 const 声明变量必须设置初始值
// 正确的做法:使用 const 声明常量并设置初始值
const PI = 3.14;
console.log(PI); // 输出: 3.14
// 错误的做法:使用 const 声明常量但不设置初始值,会报错
// const E; // 这里会抛出 SyntaxError 错误
3.var存在变量提升,let和const不存在变量提升,即在变量只能在声明之后使用,否在会报错
console.log(num); // 输出: undefined
var num = 10;
console.log(num); // 输出: 10
在上述代码中,虽然 var num = 10; 语句在 console.log(num); 之后,但由于 var 存在变量提升,相当于代码在执行前被解析为如下形式
var num;
console.log(num); // 此时 num 被初始化为 undefined
num = 10;
console.log(num); // 输出: 10
let 不存在变量提升
// 这里会抛出 ReferenceError 错误,因为在 let 声明之前访问变量
// console.log(name);
let name = 'John';
console.log(name); // 输出: John
const 不存在变量提升
// 这里会抛出 ReferenceError 错误,因为在 const 声明之前访问变量
// console.log(age);
const age = 25;
console.log(age); // 输出: 25
4.let和const具有块级作用域,var不存在块级作用域。块级作用域解决了ES5中的两个问题: 内层变量可能覆盖外层变量 用来计数的循环变量泄露为全局变量 写例子
(一) 内层变量可能覆盖外层变量
var num = 10;
function test() {
var num = 20;
console.log(num); // 输出 20,内层变量覆盖了外层变量
}
test();
console.log(num); // 输出 10,因为 var 没有块级作用域,外层变量未受影响
在上述代码中,var 声明的变量没有块级作用域,函数内部的 num 变量覆盖了外部的 num 变量。
全局作用域:在全局作用域中,使用 var 声明了变量 num 并赋值为 10。
函数作用域:在 test 函数内部,又使用 var 声明了一个同名变量 num 并赋值为 20。由于 var 没有块级作用域,但是有函数作用域,所以函数内部的 num 是一个新的局部变量,它只在 test 函数内部有效。
函数内部输出:当在 test 函数内部调用 console.log(num) 时,会输出函数内部的 num 的值,即 20。
全局输出:当在函数外部调用 console.log(num) 时,会输出全局作用域中的 num 的值,即 10。
使用 let 和 const 的情况
let num = 10;
function test() {
let num = 20;
console.log(num); // 输出 20,内层变量在块级作用域内有效
}
test();
console.log(num); // 输出 10,外层变量不受内层变量影响
const num2 = 30;
function test2() {
const num2 = 40;
console.log(num2); // 输出 40,内层变量在块级作用域内有效
}
test2();
console.log(num2); // 输出 30,外层变量不受内层变量影响
在这个案例中,使用 let 声明的变量具有块级作用域。在块级作用域内部声明的 num 只在该块级作用域内有效,不会影响到外部的 num。
综上所述,原案例中使用 var 声明的变量,函数内部的变量只是在函数作用域内有效,并没有真正覆盖全局作用域中的同名变量。
(二)用来计数的循环变量泄露为全局变量
使用 var 的情况
for (var i = 0; i < 5; i++) {
console.log(i); // 依次输出 0, 1, 2, 3, 4
}
console.log(i); // 输出 5,循环结束后,var 声明的 i 泄露为全局变量
使用 let 和 const 的情况
for (let j = 0; j < 5; j++) {
console.log(j); // 依次输出 0, 1, 2, 3, 4
}
// console.log(j); // 这里会报错,因为 j 只在 for 循环的块级作用域内有效
for (const k = 0; k < 1; k++) { // 注意:const 声明的变量不能重新赋值,这里 k 只能使用一次
console.log(k); // 输出 0
}
// console.log(k); // 这里会报错,因为 k 只在 for 循环的块级作用域内有效