ECMAScript 6 introduced the let statement.

我听说它被描述为一个local变量,但我仍然不确定它的行为与var关键字有什么不同.

有什么不同?什么时候应该用let而不是var

推荐答案

Scoping rules

主要区别在于作用域规则.由var关键字声明的变量的作用域为直接函数体(因此为函数作用域),而let个变量的作用域为由{ }表示的即时enclosing挡路(因此为挡路作用域).

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中错误的主要来源之一.

让我们来看看这个来自another Stack Overflow question的例子:

var funcs = [];
// let's create 3 functions
for (var i = 0; i < 3; i++) {
  // and store them in funcs
  funcs[i] = function() {
    // each should log its value.
    console.log("My value: " + i);
  };
}
for (var j = 0; j < 3; j++) {
  // and now let's run each one to see
  funcs[j]();
}

由于匿名函数绑定到同一个变量,所以每次调用funcs[j]();时,都会将My value: 3输出到控制台.

人们必须创建立即调用的函数来从循环中捕获正确的值,但这也很麻烦.

Hoisting

而用var关键字声明的变量是hoisted(在代码运行之前用undefined初始化),这意味着即使在声明它们之前,也可以在它们的封闭作用域中访问它们:

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

run();

let个变量在其定义被判断之前不会初始化.在初始化之前访问它们会导致错误.从块的开始到初始化被处理,变量被称为处于"时间死区".

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

checkHoisting();

Creating global object property

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

var foo = "Foo";  // globally scoped
let bar = "Bar"; // not allowed to be globally scoped

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

Redeclaration

在严格模式下,var将允许您在同一范围内重新声明同一变量,而let将引发SyntaxError.

'use strict';
var foo = "foo1";
var foo = "foo2"; // No problem, 'foo1' is replaced with 'foo2'.

let bar = "bar1"; 
let bar = "bar2"; // SyntaxError: Identifier 'bar' has already been declared

Javascript相关问答推荐

从连接字符串创建客户端时,NodeJS连接到CosmosDB失败

如何提取Cypress中文本

确定MutationRecord中removedNodes的索引

Vega中的模运算符

TypScript界面中的Infer React子props

每次子路由重定向都会调用父加载器函数

按下同意按钮与 puppeteer 师

获取Uint8ClampedArray中像素数组的宽度/高度

为什么useState触发具有相同值的呈现

从页面到应用程序(NextJS):REST.STATUS不是一个函数

如何将数组用作复合函数参数?

当用户点击保存按钮时,如何实现任务的更改?

将数组扩展到对象中

TinyMCE 6导致Data:Image对象通过提供的脚本过度上载

为什么当我更新数据库时,我的所有组件都重新呈现?

try 将Redux工具包与MUI ToggleButtonGroup组件一起使用时出错

如何根据输入数量正确显示alert ?

Socket.IO在刷新页面时执行函数两次

如何使用[ModelJSON,ArrayBuffer]调用tf.loadGraphModelSync

我在哪里添加过滤器值到这个函数?