let
我听说它被描述为一个local变量,但我仍然不太确定它的行为与var关键字有何不同。
local
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 中错误的主要来源之一。
查看此示例:
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](); }
My value: 3每次funcs[j]();调用时都会输出到控制台,因为匿名函数绑定到同一个变量。
My value: 3
funcs[j]();
人们必须创建立即调用的函数来从循环中捕获正确的值,但这也很麻烦。
虽然用var关键字声明的变量被hoisted(undefined在代码运行之前用初始化),这意味着它们甚至在声明之前就可以在其封闭范围内访问:
undefined
function run() { console.log(foo); // undefined var foo = "Foo"; console.log(foo); // Foo } run();
let变量在其定义被评估之前不会被初始化。在初始化之前访问它们会导致ReferenceError. 从块的开始直到处理初始化,变量被称为处于“时间死区”。
ReferenceError
function checkHoisting() { console.log(foo); // ReferenceError let foo = "Foo"; console.log(foo); // Foo } checkHoisting();
在顶层let,与 不同var,不会在全局对象上创建属性:
var foo = "Foo"; // globally scoped let bar = "Bar"; // not allowed to be globally scoped console.log(window.foo); // Foo console.log(window.bar); // undefined
在严格模式下,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