JavaScript中var、let、const的区别与使用指南
本文深入解析JavaScript中var、let、const三种变量声明方式的核心区别。重点阐述var的函数作用域与变量提升特性,对比let和const的块级作用域、暂时性死区及不可重声明规则。通过代码示例说明const在引用类型中的行为,并给出ES6推荐的最佳实践建议。
一、什么是变量
在深入阅读之前,明确变量的定义至关重要。简单来说,变量是一个可以保存任何数据类型值的命名占位符。。本文将围绕以下核心知识点展开:
- 什么是var、let、const
- 变量声明规则
- 变量提升
- 块作用域
- 暂时性死区
二、var关键字
2.1 初始化
初始化变量只需在var关键字后跟随变量名即可:
var a;
var b = 2;上述代码声明了a和b两个变量。其中a仅被声明而未赋值,JavaScript引擎会自动为其赋予undefined;变量b在声明时赋值为数字2,因此获取b时将得到类型为number的2。
提及number类型,需了解JavaScript采用松散类型系统,即变量值可被重新赋值为任意数据类型。尽管技术上可行,但随意更改变量类型会降低代码可读性,故不推荐此做法。
// 翻译后是var a = undefined;
var a;
var b = 2;
b = '2'; // 不建议这么做在开发中若需创建多个变量,除var a = 1; var b = 2;这种写法外,还可利用,符号实现更便捷的批量声明:
// 使用逗号创建多个变量
var a = 1,
b = 2,
c = 3;
// 等同于
var a = 1;
var b = 2;
var c = 3;2.2 var声明作用域
变量的作用域由其声明位置决定,主要包含两种场景:全局、函数。在全局作用域声明的var变量可在任何地方访问,且可通过window.变量名属性访问。若在函数内部声明,则该变量仅属于该函数,外部访问将报错,并在函数执行结束后被销毁。
// 声明全局变量
var a = 1;
// 访问全局变量
console.log(a); // 1
console.log(window.a); // 1
// 声明函数作用域内的变量
function fun () {
var b = 2; // 只属于fun函数的变量
console.log(b); // 2
};
fun(); // 2
console.log(b); // 报错:b is not defined(变量b未定义)2.3 var的变量提升
变量提升指var声明在初始化阶段会被提升至当前作用域顶部,且初始值均为undefined。仅当执行到赋值语句时,变量才获得具体值。基于此原理,分析以下代码的执行结果:
var a = 1,
b = 2;
function fun (a) {
console.log(b);
var b = 6;
var b = 5;
console.log(a);
console.log(b);
};
console.log(b);
fun(4);
console.log(b);该代码虽无复杂交互,但多次变量访问易造成混淆。我们逐步分解以验证结果:
- 全局作用域中存在三个变量:
a、b、fun(函数名本身也是变量) - 在函数执行前打印全局变量b,结果为
2 - 调用函数并传入参数,开始执行函数内部逻辑
- 此时函数内部的变量a和b均提升至作用域顶部,初始值均为undefined
- 变量a被赋值为4
- 打印变量b,因尚未赋值,结果为
undefined - 变量b开始赋值,但遇到同名变量,后声明的变量覆盖前者
- 获取变量a,此前传参时已赋值为4,故结果为
4 - 由于之前的变量b被后续声明覆盖,此时获取b的结果为
5 - 函数内部代码执行完毕,转而获取外部变量b的值
- 尽管函数内部有b变量,但其属于函数局部作用域,执行完毕后已销毁,因此只能获取全局作用域下的b,值为
2
最终输出结果为:2、undefined、4、5、2。
全局变量
全局变量除最外层声明外,还有一种非推荐方式:
var a = 1; // 正常的声明全局变量
function fun () {
b = 2; // 变量名前面没有写var,默认成为全局作用域
};
// 因为函数还没有执行,所以这块会报错
console.log(b); // b not defined
fun();
console.log(b); // 2三、let声明
3.1 块级作用域
相较于var,let更为严谨,其最大区别在于支持块级作用域。所谓块级作用域,即{}符号包裹的区域,该规则对var无效。
块级作用域与函数作用域类似,用于控制内部变量的访问权限
{ // 块级作用域
let a1 = 2;
}
console.log(a1); // 报错:a1 is not defined3.2 暂时性死区
在let声明之前的代码执行阶段被称为暂时性死区。此阶段无法访问let变量,因为let不存在变量提升机制。此外,let禁止重复声明,若尝试声明同名变量将引发错误,这与var允许重复声明不同。
{
console.log(b); // 因为没有变量提升,所以在声明前访问不到该变量,报错:annot access 'b' before initialization
let b = 1;
}
let a = 1;
let a = 2; // 重名变量会报错:caught SyntaxError: Identifier 'a' has already been declaredlet的全局作用域
尽管let主要作用于块级,但在最外层全局作用域声明的let变量仍被视为合法全局变量。与var不同,let声明的全局变量无法通过window.变量名访问。
for循环中的let和var
for循环会不断生成新的块级作用域,导致var和let在迭代更新上表现不同:
let arr = [1, 2, 3, 4, 5];
for (let i = 0; i < arr.length; i++) {};
console.log(i); // 报错:i is not defined
for (var i = 0; i < arr.length; i++) {};
console.log(i); // 5上述代码第一个循环使用let声明变量,在循环外访问时报错,原因是循环体使用了{}形成了块级作用域,块外无法访问let变量。而var变量不受块级作用域限制,成为全局变量,因此访问var变量不会报错。
四、const声明
const用于声明常量,为便于理解,下文仍沿用变量概念进行介绍
const与let规则高度相似:不能声明重名变量、存在暂时性死区、没有变量提升、有块级作用域限制。在此基础上,const额外增加了两条规则:1、声明时必须赋值;2、值不可修改;
声明时必须赋值,即创建时需赋予初始值。重点说明值不可修改这一特性:
const a = '2';
a = 2; // 报错a变量已经声明,不能重复创建:entifier 'a' has already been declared上述代码首先创建const变量并赋值为字符串'2',第二行尝试赋值为数字2时因常量不可修改而报错。由此可见,const适用于值不变的场景。若const赋值为数组或对象等引用类型,只要引用地址不变,修改、新增或删除内部元素不会报错。
总结
综上所述,最佳实践为:尽量避免使用var;变量值需变化时使用let;值无需改变时使用const。
| var | let | const | |
|---|---|---|---|
| 变量提升 | √ | × | × |
| 重复声明相同名称变量 | √ | × | × |
| 是否可以更改变量值 | √ | √ | × |
| 函数作用域 | √ | × | × |
| 块作用域 | × | √ | √ |
关于js中var、let、const之间的区别的文章就介绍到这了,更多相关js var let const内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
JS中将数组和对象混合组装为JSON字符串
2026-11-05 16:41:42
JS运算符优先级与结合性的区别是什么?
2026-11-05 13:22:02
JS Map怎么只遍历Key或Value
2026-11-05 13:00:36
D3.js 与 ECharts 选型对比:灵活性 vs 开发效率
2026-11-05 09:45:01
为什么JS中typeof []返回object:数组类型检测误区解析
2026-11-04 19:50:47
