发布于 2026-01-06 0 阅读
0

var、let、const:它们有什么区别?

var、let、const:它们有什么区别?

今天我们要讨论一个对 JavaScript 开发者来说非常重要的主题。你可能每天都会用到 var、let 和/或 const,但你知道它们之间的区别吗?这就是我们今天要讨论的内容。

var

这种var语句现在越来越少用了,但这并不意味着它不好。
事实上,它的一些特殊用法反而会降低代码的可预测性。

重新分配

使用 `std::vector` 声明的变量var可以被重新赋值:

var myVariable = "First value";

myVariable = "Second value";
Enter fullscreen mode Exit fullscreen mode

*注意:您并非必须初始化它:

var notInitializedVar;
Enter fullscreen mode Exit fullscreen mode

var同名声明

您可以声明多个同名(或标签)的变量:

var redeclaredVar = 'First declaration';

var redeclaredVar = 'Second declaration';
Enter fullscreen mode Exit fullscreen mode

范围var

作用域var取决于其声明位置。

在函数中

当在函数内部声明时,其作用域将是整个函数。是的,即使你将其声明在 `<div>` 标签内if,它也可以在该标签外部访问:

function myDummyFunction() {
  if (true) {
    var myVariable = "A variable declared with var";
  }

  console.log(myVariable);
}

// Will print "A variable declared with var"
myDummyFunction();
Enter fullscreen mode Exit fullscreen mode

注意:该变量也可以在“代码块”(例如if代码块或内部函数)内部访问:

function myDummyFunction() {
  var myVariable = "A variable declared with var";

  if (true) {
    console.log(myVariable);
  }
}

// Will print "A variable declared with var"
myDummyFunction();
Enter fullscreen mode Exit fullscreen mode

在函数之外

var当我们在函数外部声明变量时,该变量将是全局作用域的变量。

例如,如果您在浏览器的开发者工具中输入:

var myGlobalVariable =
  "Hello, I will be accessible from the window";

// Will print "Hello, I will be accessible from the window"
console.log(window.myGlobalVariable);
Enter fullscreen mode Exit fullscreen mode

警告:在使用 ES 模块和 commonJS 模块时,此变量的作用域仅限于该模块

注意:这就是立即调用函数表达式 (IIFE) 诞生的原因,为了防止变量处于全局作用域并与其他库中的变量发生冲突。

吊装

首先,我们来定义一下什么是变量提升:它是一种自动将变量或函数放到文件顶部的行为。
正因为有了变量提升,你才能在使用函数之后再声明它:

hoistedFunction();

function hoistedFunction() {
  console.log("I can be called before my declaration");
}
Enter fullscreen mode Exit fullscreen mode

的特殊之处在于var,变量会被提升到文件顶部或函数顶部(如果在函数内部声明),并且会被初始化为 undefined

// Will print "undefined"
console.log(myHoistedVar);

var myHoistedVar = "I am a hoisted and initialized var";
Enter fullscreen mode Exit fullscreen mode
function myDummyFunction() {
  // Look the variable is declared inside the if
  // and the condition is always false
  console.log(myVariable);

  if (false) {
    var myVariable = "A variable declared with var";
  }
}

// Will print "undefined"
myDummyFunction();
Enter fullscreen mode Exit fullscreen mode

未限定标识符分配

在非严格模式下(不使用 `\s` use strict;),如果您声明了一个变量,只使用了变量名而没有使用限定符(`\n` varlet`\s` 或const`\s`),则该变量名将自动赋值给 `\s` var

unqualifiedVar =
  "I will be automatically be qualified \
with var in non strict mode";

// This will be transformed into
var unqualifiedVar =
  "I will be automatically be qualified \
with var in non strict mode";
Enter fullscreen mode Exit fullscreen mode

警告:在严格模式下,它将无法工作,并会抛出ReferenceError异常。

"use strict";

// You will see in your console something like
// Uncaught ReferenceError: unqualifiedVar is not defined
unqualifiedVar = "Will throw a ReferenceError";
Enter fullscreen mode Exit fullscreen mode

let

在日常生活中,你可能let比使用变量更频繁地使用var它。但让我们回顾一下相关的知识:

重新分配

例如var,你可以重新赋值一个用以下方式声明的变量let

let myVariable = "First value";

myVariable = "Second value";
Enter fullscreen mode Exit fullscreen mode

范围let

这是与 . 的主要区别之一。使用var. 限定的变量let将是块级作用域的(即只能在当前更近的父级大括号内访问)。

function myDummyFunction() {
  let myVariable = "A let variable";

  if (true) {
    console.log(myVariable);
  }
}

// Will print "A let variable"
myDummyFunction();
Enter fullscreen mode Exit fullscreen mode

与此不同的是,如果您尝试访问在内部代码块中声明的变量,var它将抛出异常:ReferenceError

function myDummyFunction() {
  if (true) {
    let myVariable = "A let variable";
  }

  console.log(myVariable);
}

// You will see in your console something like
// Uncaught ReferenceError: myVariable is not defined
myDummyFunction();
Enter fullscreen mode Exit fullscreen mode

注意:使用 `with` 声明的变量永远let不会全局作用域的。

无法重新定义同一个标签

与此不同的是var,你不能定义另一个具有相同标签(标识符)的变量。否则,你会在控制台中看到一个语法错误。

let myLetVariable = "First value";

// You will see in your console something like
// Uncaught SyntaxError: Identifier 'myLetVariable' has
// already been declared
let myLetVariable = "Second value";
Enter fullscreen mode Exit fullscreen mode

hoisting

尽管你在网上可能看到一些例子let(例如const),但它们会被提升,而与它们的区别var在于它们不会被初始化undefined
在变量初始化之前ReferenceError,如果你尝试访问它,就会出现错误。

console.log(myLetVariable);

// You will see in your console something like
// Uncaught ReferenceError: myLetVariable is not defined
let myLetVariable = "Some value";

// From here no more TDZ
Enter fullscreen mode Exit fullscreen mode

这种现象被称为时间死区

如果你问为什么使用“临时性”这个词?
实际上,这是因为这取决于代码的执行时间。例如,如果你有以下代码,那就完全没问题:

setTimeout(() => console.log(myLetVariable)), 500;

let myLetVariable = "Some value";

// After 500 ms you will see
// "Some value" prints in the console
Enter fullscreen mode Exit fullscreen mode

const

使用 `__init__` 声明的变量与使用 `__init__` 声明的const变量具有非常相似的属性let。唯一的区别在于重新赋值初始化

不重新分配

使用 `&` 声明的变量const,无法将其重新赋值给另一个值:

const myConstVariable = "First value";

// You will see in your console something like
// Uncaught TypeError: Assignment to constant variable
myConstVariable = "Second value";
Enter fullscreen mode Exit fullscreen mode

警告:const使用 ` is mutable`声明的变量

const person = {};

// Mutation is done here
person.firstName = "Romain";
Enter fullscreen mode Exit fullscreen mode

初始化

你必须初始化一个带有限定符的变量const,否则你会遇到语法错误

// You will see in your console something like
// Uncaught SyntaxError: Missing initializer in const declaration
const uninitializedConst;
Enter fullscreen mode Exit fullscreen mode

结论

我希望你现在思路更清晰了。如果你必须记住什么,我想应该是 ` /`varlet`*`的作用域const不同。`
var/` 在函数内部声明时具有函数作用域,在函数外部声明时具有全局作用域。`/`具有块级作用域。let`/` 不同,`/` 中的变量可以被重新赋值。但是要注意,用 `/` 声明的变量不是不可变的。 这三个变量都会被提升,但 `/`会被初始化为`null` ,而`/` 和`*` 则不会。const
letconstconst
varundefinedletconst

以下是一个简单的表格:

重新分配 重新声明 范围 吊装 未限定变量
变量 ✔️ ✔️ 函数或全局 ✔️(初始化为 undefined) 真的
✔️ ✖️ 堵塞 ✔️(未初始化,TDZ) ✖️
常量 ✖️ ✖️ 堵塞 ✔️(未初始化,TDZ) ✖️

欢迎留言评论,如果想看更多内容,可以关注我的推特或访问我的网站。🐼

文章来源:https://dev.to/romaintrotard/var-let-const-what-s-the-difference-2eh0