"let" 和 "var" 的区别是什么?

发布时间 2023-10-08 21:02:59作者: 小满独家

内容来自 DOC[ https://q.houxu6.top/?s="let" 和 "var" 的区别是什么?](https://q.houxu6.top/?s="let" 和 "var" 的区别是什么?)

ECMAScript 6引入了let语句

我听说它被描述为一个局部变量,但我仍然不太清楚它与var关键字的行为有什么不同。

它们之间的区别是什么?什么时候应该使用let代替var


作用域规则

主要区别在于作用域规则。var关键字声明的变量作用域为函数体(因此为函数作用域),而let变量作用域为由{ }表示的立即包围块(因此为块作用域)。

function run() {
  var foo = "Foo";
  let bar = "Bar";

  console.log(foo, bar); // Foo Bar

  {
    var moo = "Mooo"
    let baz = "Bazz";
    console.log(moo, baz); // Mooo Bazz
  }

  console.log(moo); // Mooo
  console.log(baz); // ReferenceError
}

run();

let关键字被引入语言的原因是函数作用域令人困惑,并且是JavaScript中的主要错误来源之一。

看看这个来自Stack Overflow另一个问题的示例:

var funcs = [];
// 让我们创建3个函数
for (var i = 0; i < 3; i++) {
  // 并将它们存储在funcs中
  funcs[i] = function() {
    // 每个都应该记录其值。
    console.log("My value: " + i);
  };
}
for (var j = 0; j < 3; j++) {
  // 现在让我们运行每个函数以查看
  funcs[j]();
}

每次调用funcs[j]();时,My value: 3都会被输出到控制台,因为匿名函数绑定到了相同的变量。

人们不得不创建立即调用的函数来捕获循环中的正确值,但这也很棘手。

提升

虽然使用var关键字声明的变量会被提升(在代码运行之前用undefined初始化),这意味着它们在包围范围内可访问,直到它们的定义被评估:

function run() {
  console.log(foo); // undefined
  var foo = "Foo";
  console.log(foo); // Foo
}

run();

let变量在初始化之前不会被初始化,直到它们的定义被评估。在初始化处理之前访问它们会导致ReferenceError。该变量从块的开始处被称为“临时死区”。

function checkHoisting() {
  console.log(foo); // ReferenceError
  let foo = "Foo";
  console.log(foo); // Foo
}

checkHoisting();

创建全局对象属性

在顶层,与var不同,let不会在全局对象上创建属性:

var foo = "Foo";  // 全局作用域
let bar = "Bar"; // 不允许全局作用域

console.log(window.foo); // Foo
console.log(window.bar); // undefined

重新声明

在严格模式下,var将允许您在同一作用域中重新声明相同的变量,而let会引发语法错误。

'use strict';
var foo = "foo1";
var foo = "foo2"; // 没有问题,'foo1'被替换为'foo2'。

let bar = "bar1"; 
let bar = "bar2"; // 语法错误:标识符'bar'已经被声明过了