JavaScript 中 var 与 TypeScript 中 let 的区别及使用场景

51 阅读5分钟

JavaScript 中 var 与 TypeScript 中 let 的区别及使用场景

在 JavaScript 和 TypeScript 的学习过程中,变量声明是基础中的基础。其中,var和let是两种常用的变量声明方式,它们在特性和使用场景上存在明显差异。对于初学者来说,搞清楚这些差异有助于写出更规范、更可靠的代码。

一、作用域不同

作用域指的是变量可以被访问的范围,这是var和let最核心的区别之一。

var 的作用域

var声明的变量具有函数作用域,也就是说,变量只在声明它的函数内部可以被访问,在函数外部则无法访问。如果在函数外部使用var声明变量,那么这个变量就会成为全局变量,属于全局对象(在浏览器中是window对象)的属性。

例如:

function testVar() {
  var a = 10;
  console.log(a); // 输出10,在函数内部可以访问
}
testVar();
console.log(a); // 报错,在函数外部无法访问a

再看一个全局声明的例子:

var globalVar = "我是全局变量";
console.log(window.globalVar); // 输出"我是全局变量",成为window的属性

另外,var没有块级作用域的概念。所谓块级作用域,是指由{}包裹的代码块(如if语句、for循环等)形成的作用域。在块级作用域内用var声明的变量,在块级作用域外部仍然可以被访问。

比如:

if (true) {
  var b = 20;
}
console.log(b); // 输出20,在if块外部可以访问b

let 的作用域

let声明的变量具有块级作用域,变量只在声明它的块级作用域(由{}包裹的范围)内可以被访问,在块级作用域外部无法访问。

例如:

if (true) {
  let c = 30;
  console.log(c); // 输出30,在if块内部可以访问
}
console.log(c); // 报错,在if块外部无法访问c

在函数中使用let声明变量,变量的作用域也局限于函数内部,这一点和var类似,但在嵌套的块级作用域中表现不同:

function testLet() {
  let d = 40;
  if (true) {
    let d = 50; // 这里的d是一个新的变量,与外部的d不冲突
    console.log(d); // 输出50
  }
  console.log(d); // 输出40
}
testLet();

二、变量提升差异

变量提升是 JavaScript 的一种特性,指的是变量声明会被提升到当前作用域的顶部,但赋值操作不会被提升。var和let在变量提升方面的表现也有所不同。

var 的变量提升

var声明的变量会被完全提升,在声明之前就可以访问该变量,只是此时变量的值为undefined。

例如:

console.log(e); // 输出undefined,不会报错
var e = 60;

上面的代码实际上会被 JavaScript 引擎解析为:

var e; // 变量声明被提升到顶部
console.log(e);
e = 60; // 赋值操作留在原地

let 的变量提升

let声明的变量也会被提升,但它存在一个 “暂时性死区”。在变量声明之前的区域就是 “暂时性死区”,在这个区域内访问该变量会直接报错。

例如:

console.log(f); // 报错,Cannot access 'f' before initialization
let f = 70;

这是因为let的变量提升不会像var那样允许在声明前访问,它更严格地遵循了 “先声明后使用” 的原则,有助于减少代码中的逻辑错误。

三、重复声明的限制

在同一个作用域内,var和let对重复声明变量的限制也不同。

var 允许重复声明

var可以在同一个作用域内重复声明同一个变量,后面的声明会覆盖前面的声明。

例如:

var g = 80;
var g = 90;
console.log(g); // 输出90,后面的声明覆盖了前面的

let 不允许重复声明

let在同一个作用域内不允许重复声明同一个变量,否则会直接报错。

例如:

let h = 100;
let h = 110; // 报错,Identifier 'h' has already been declared

这种限制可以避免因不小心重复声明变量而导致的意外错误,让代码更健壮。

四、使用场景建议

了解了var和let的区别后,我们可以根据具体场景选择合适的声明方式。

var 的使用场景

由于var存在函数作用域、允许重复声明、变量提升等特性,在现代 JavaScript 和 TypeScript 开发中,var的使用场景已经非常有限。一般来说,只有在维护一些老旧的 JavaScript 代码时,可能会遇到var,在新的开发项目中,不建议优先使用var

let 的使用场景

let是 TypeScript 以及现代 JavaScript 开发中的首选变量声明方式,尤其适用于以下场景:

  1. 块级作用域需求:当需要在if、for、while等块级作用域内声明变量,且不希望变量泄露到块级作用域外部时,使用let。例如在for循环中声明循环变量:
for (let i = 0; i < 5; i++) {
  console.log(i); // 每次循环的i都是一个新的变量,作用域仅限于当前循环体
}
console.log(i); // 报错,在循环外部无法访问i
  1. 避免变量提升问题:当希望变量必须先声明后使用,以减少因变量提升导致的逻辑错误时,使用let。
  1. 防止重复声明:在团队协作或大型项目中,为了避免不小心重复声明变量而引发问题,使用let可以提前发现错误。

总之,在 TypeScript 开发中,let是更推荐的变量声明方式,它的块级作用域、暂时性死区和禁止重复声明等特性,能让代码更具可读性、可维护性和健壮性。而var由于自身的局限性,在新的开发项目中应尽量避免使用。