浅析var、let、const的区别

92 阅读5分钟

前言

JavaScript作为一门广泛使用的编程语言,在其发展过程中经历了多个版本的更新。ES6(ECMAScript 2015)作为一次重要的升级,引入了许多新特性,其中就包括了对变量声明方式的改进——新增了letconst关键字,它们在作用域、重声明以及赋值方面与传统的var关键字有着显著的不同。

1. 什么是作用域

作用域是指程序中定义变量和函数的可访问范围。在JavaScript中,根据ES5和ES6的不同,作用域主要分为全局作用域、函数作用域和块级作用域。

  • 全局作用域:当变量或函数在最外层定义时,即不在任何函数或块内定义,它们就处于全局作用域中。这意味着这些变量或函数可以在程序的任何地方被访问。在Web浏览器环境中,全局作用域通常与window对象相关联,所有全局变量都是window对象的属性。为了减少潜在的冲突和提高代码质量,建议尽量减少全局变量的使用。
  • 函数作用域:这是指在函数内部定义的变量和函数,它们仅在该函数内部可见。函数作用域是ES5及之前的JavaScript版本中唯一存在的局部作用域类型。在函数作用域中声明的变量只能在该函数及其嵌套的任何函数中访问。
  • 块级作用域:ES6引入了块级作用域的概念,允许开发者在由大括号 {} 包围的代码块中定义变量。这种作用域通过letconst关键字实现,它们声明的变量仅在声明它们的代码块内可见。与var不同,letconst声明的变量不会被提升到其作用域的顶部,这意味着它们在声明之前是不可访问的,这被称为“暂时性死区”。

JavaScript中变量的声明方式对作用域有着重要影响:

  • var:这是ES5中用来声明变量的关键字,具有函数作用域(如果在函数内部声明)或全局作用域(如果在函数外部声明)。var声明的变量会被提升至其作用域的顶部,即使实际声明出现在代码的后面。
  • letconst:这两个关键字是从ES6开始引入的,用于声明具有块级作用域的变量。let用于声明一个可以重新赋值的变量,而const用于声明一个一旦初始化后就不能改变其值的常量。使用letconst声明的变量不会被提升,因此在声明前尝试访问这些变量会导致引用错误。

了解这些作用域规则对于编写清晰、维护性强的JavaScript代码至关重要。正确地管理作用域不仅可以避免变量名冲突,还可以帮助减少内存泄漏的风险。

2. var 关键字

var 是ES5及更早版本中用于声明变量的关键字,同时我们可以在声明语句中初始化所声明的变量。

var a = 10;

它具有函数作用域或全局作用域,这意味着在函数内部使用var声明的变量在整个函数体内都是可见的;而在全局作用域下声明的变量则可以在整个程序中访问。

function example() {
  var a =10;
  console.log(a);  // 输出 10
  if(true) {
   var a=20;
   console.log(a); // 输出 20
  }
  console.log(a);  // 输出 20
}

此外,var允许在同一作用域内重复声明同一个变量名,这可能导致意外的覆盖问题。

3. let 关键字

ES6引入了let关键字来声明变量,和 var 类似,我们可以在声明时初始化它的值。

let a = 10;

var相比,let提供了更严格的变量管理机制。最显著的变化在于let支持块级作用域,即在大括号{}内的变量只在这个块内有效,不会污染外部环境。同时,let不允许在同一作用域内重复声明同一个变量名,有助于减少命名冲突的问题。

function example() {
    if (true) {
        let y = 20;
    }
    console.log(y);
}
// 抛出错误: y is not defined
{
  let x = 5;
  let x = 10; // SyntaxError: Identifier 'x' has already been declared
}

4. const 关键字

同样是在ES6中引入,const用于声明常量,const 语句的作用范围和 let 语句一样。const也遵循块级作用域规则,并且要求在声明时必须初始化。

const a = 10;
function example() {
  const MY_VARIABLE =10;
  console.log(MY_VARIABLE);  // 输出 10 
}

照例,命名规范指出我们应该用大写字母声明常量。当然,const a = 10 在上面的代码中会的起到相同的作用。为了让代码长期可维护,命名规范还是值得遵守的。

一旦使用const声明了一个变量,就不能再次赋值。需要注意的是,对于复杂数据类型(如对象和数组),虽然不能重新赋值给const变量,但是可以修改这些数据类型的内部属性或元素。

function example() {
  const MY_VARIABLE =10;
  console.log(MY_VARIABLE);  // 输出 10
  MY_VARIABLE =20;           // 抛出类型错误
  console.log(MY_VARIABLE); 
}
const obj = { name: 'AAA' };
obj.name = 'BBB'; // 合法,修改了 obj 的属性,但没有改变 obj 的引用
console.log(obj); // 输出: { name: 'BBB' }

const arr = [1, 2, 3];
arr[0] = 4; // 合法,修改了 arr 的第一个元素,但没有改变 arr 的引用
console.log(arr); // 输出: [4, 2, 3]

总结

  • 作用域var拥有函数作用域或全局作用域,而letconst则具备更精细的块级作用域。
  • 重声明var允许在同一个作用域内多次声明相同的变量,而letconst则禁止这种行为。
  • 赋值varlet都可以随时更改变量的值,但const声明的变量在声明时必须赋初值,且之后不能更改其引用(对于基本数据类型而言是值本身,对于引用数据类型则是内存地址)。

通过理解这些差异,我们可以根据实际需求选择合适的变量声明方式,从而编写出更加安全、高效且易于维护的代码。

R-C.png 点个赞再走吧~