JavaScript 变量声明:var、let 与 const 详解

作者:代码拾荒时间:2026-10-24 22:32:13浏览:155

本文深入解析 JavaScript 中 var、let 和 const 三种变量声明方式。重点对比它们的作用域差异(函数作用域与块作用域)、变量提升机制以及 const 的常量限制。通过代码示例说明重复声明、全局对象属性及暂时性死区等关键概念,帮助开发者规范变量使用。

变量

在 ECMAScript 规范中,变量具备“松散”特性,能够存储任意类型的数据(包括字符串、数组或其他类型)。变量本质上是一个用于标识数据的占位符。目前 JavaScript 提供了三个关键字来声明变量:var、const 和 let。其中,var 关键字在所有 ECMAScript 版本中均有效,而 const 和 let 仅在 ES6 及更高版本中可用。

(一)var

var a;//仅定义
var b=‘hi';//定义的同时,设置值

需要注意的是,变量的值可以被后续赋值覆盖,但这种做法并不推荐。

var a=”hello”
a=”hi”

由于 ECMAScript 变量具有松散类型特性,可以在一条语句中同时声明并初始化不同数据类型的变量。虽然插入换行并非强制要求,但必须使用逗号分隔各个变量声明。

Var a=“hello”,
    b=12,
    c=false;

1)关于 var 声明的变量的作用域

function test(){
    var a="shanxi";
}
test();//调用函数
console.log(a);
//ReferenceError: a is not defined
//报错:a未定义

当使用 var 定义变量时,如果该变量位于函数内部,则其作用域仅限于该函数。一旦函数执行结束,变量将被销毁,无法再被外部调用。例如,在函数 test 内部使用 var 定义变量 a,在调用函数 test 后,变量 a 随即被销毁,因此再次访问 a 会引发报错。

如果在声明变量时省略了关键词 var,该变量将自动成为全局变量。尽管这种方式可行,但强烈不建议使用,因为过多的全局变量会导致程序难以维护。

function test(){
    a="sichuan";
}
test();//调用函数
console.log(a);
//sichuan

2)var 声明提升(hoist)

如下代码运行结果为 undefined 而非报错,这是因为使用 var 关键字声明的变量会自动提升到其所在函数作用域的顶部。也就是说,ECMAScript 引擎会将代码解释为如下形式:

function test(){
   console.log(a)
   var a=12;
}
test()
//undefined

也就是,会被 ECMAScript 看作

function test(){
   var a; 
   console.log(a)
   a=12;
}
test()
//undefined

这种“提升”机制会将所有变量的声明语句移动到函数作用域的顶部,而赋值操作仍保留在原位。

(二)let

let 声明与 var 类似,主要区别在于作用域范围:let 声明的变量具有块作用域,而 var 声明的变量具有函数作用域。

例如,在 if 语句中的 {} 就是一个“块”,它构成了一个独立的作用域,而非函数作用域。

if(true){
    var b="zhang"
    console.log(b);//zhang
}
console.log(b);//zhang

换成 let:

if(true){
    let b="zhang"
    console.log(b);//zhang
}
console.log(b);//ReferenceError: b is not defined

此时,变量 b 仅在定义它的块作用域内有效。在 if 语句外部(即定义 b 的块作用域之外)尝试引用 b 将无法访问。

注意:块作用域是函数作用域的子域。这意味着块作用域一定是函数作用域的一部分,但函数作用域不一定是块作用域。

注意:适用于 var 的作用域限制规则,对 let 同样适用,唯一的区别仅在于一个是函数作用域,另一个是块作用域。

关于重复声明,var 允许在同一作用域内重复声明变量而不报错,但 let 会报错。请看如下实例:

var a=24;var a=12;var a=5;console.log(a);//5let b=2;let b=4;//SyntaxError: Identifier 'b' has already been declared//运行到此处就已经报错let b=8;console.log(b);var a=24;
var a=12;
var a=5;
console.log(a);//5
let b=2;
let b=4;//SyntaxError: Identifier 'b' has already been declared
//运行到此处就已经报错
let b=8;
console.log(b);

关于嵌套使用,JavaScript 引擎会记录变量声明的标识符及其所在的块作用域。因此,在嵌套结构中使用时,只要不在同一块作用域内重复声明,就不会报错。

var a="shanxi"
console.log(a);//shanxi
if(true){
    var a="sichaun";
    console.log(a);//sichuan
}
let b=3;
console.log(b);//3
if(true){
    let b=5;
    console.log(b);//5
}

综上所述,let 和 var 的主要区别仅在于它们所声明变量的作用域类型不同。

var a;
let a;//SyntaxError: Identifier 'a' has already been declared
let c;
var c;//SyntaxError: Identifier 'c' has already been declared

1)与 var 不同,let 声明的变量不会在作用域中被提升,这一现象被称为“暂时性死区”。

console.log(a);
var a=2;//undefined
console.log(b);
let b=3;//ReferenceError: Cannot access 'b' before initialization

2)全局声明

使用 var 在全局作用域中声明的变量会自动成为 window 对象的属性,但使用 let 声明的全局变量不会成为 window 对象的属性。

var a=3;
console.log(window.a)//a
let b=10;
console.log(window.b);//undefined

不过,let 声明的变量依然处于全局作用域内(否则不会显示为“undefined”),并且会在页面生命周期内持续存在。因此,必须确保页面中不会重复声明同一个变量。

(三)Const

const 的行为基本与 let 相同,但使用 const 声明变量时,必须同时对其进行初始化。此外,尝试修改 const 声明的变量会引发报错。

const n="zhang";
n="li";//TypeError: Assignment to constant variable.
const a=12;
const  a=9;//不可以重复声明
//SyntaxError: Identifier 'a' has already been declared

当然,const 相关的限制仅适用于它指向的变量引用本身。也就是说,如果 const 指向一个对象,修改该对象内部的属性不会违反 const 的限制。

const house={};

house.name=”myhouse”;

在 let 和 const 出现之后,许多开发者不再大量使用 var,而是更多地使用 let 和 const。这使得变量具有明确的作用域、声明位置以及不可变的值。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注本站的更多内容!

作者最新文章