为什么在JavaScript中为块范围变量声明选择了名称“ let”?


306

我知道为什么要使用var该名称-它是变量,const-它是一个常数,但是for的名称后面的含义是什么let,该范围作用于当前块?随它去?


7
使用了1962年发明的BASICLET。可能有较早的语言示例。
David R Tribble

5
基本是在发明了1964年,1962年不是也见这里LET1964年5月的手册初稿第7页上有pdf的用法说明。
约瑟夫·昆西

更具体地说,const是一个常量或不可变(只读)的对象引用,其中对象本身仍然是可变的。例如。声明/分配后const foo = ['bar']foo.push('bat')仍然合法,但foo = ['bar', 'bat']不是。但这太多了。
user982671

Answers:


372

Let是早期编程语言(例如Scheme和Basic)采用的数学表达式。变量被认为是不适合较高抽象级别的低级实体,因此许多语言设计人员希望引入类似但功能更强大的概念,例如Clojure,F#,Scala,其中let可能表示值或可以分配变量,但未更改,这反过来又使编译器可以捕获更多编程错误并更好地优化代码。

JavaScript var从一开始就有了,所以他们只需要一个关键字,就从其他几十种let已经尽可能使用作为传统关键字的语言中借来了var,尽管在JavaScript中let创建了块范围局部变量。


94
而Mozilla官方文档页面引用此页面的这个问题developer.mozilla.org/en/docs/Web/JavaScript/Reference/...
萨拉特钱德拉

9
也是很不错的len('var') === len('let'),这意味着您的声明可以在编辑器中很好地对齐。我还没有发现任何暗示这是故意的,但它可能是a)视觉上令人愉悦且更具可读性,或者b)如果将两者混合使用,则令人讨厌的调试工作(无论如何这似乎是一个坏主意,但是我我已经看过了)。
brichins 17-10-25

13
换句话说,let传统上一直使用常量来描述常量,let C = the speed of light因此Javascript决定使用let来描述具有非标准作用域的变量,同时为常量引入另一个关键字。
fijiaaron

1
我不同意那let接近var。另外,Scala不使用,let所以我看不到它的相关性。
Aluan Haddad

3
@fijiaaron:非标准范围如何?整个功能不是您所说的什么块,以某种奇怪的开头开始吗?
SamB

78

我猜它遵循数学传统。在数学中,通常说“让x是任意实数”或类似的说法。


我更喜欢这个答案,因为它在我们进行代数学习时都是简短而又相关的,因此可能应该跟其他人​​指出的一样进行解释。
duduwe

69

除了对exebook的响应外,关键字let的数学用法还很好地封装了let在Javascript / ES6中使用时的作用域范围。具体来说,正如以下ES6代码不知道大括号中的分配是toPrint 何时打印出的值一样'Hello World'

let toPrint = 'Hello World.';
{
    let toPrint = 'Goodbye World.';
}
console.log(toPrint); // Prints 'Hello World'

形式化数学(尤其是证明的编写)中使用的let表示变量的当前实例仅在该逻辑思想的范围内存在。在下面的示例中,x在输入新想法时通常会获得新的标识(通常这些是证明主要想法所必需的概念),并在子证明结束后立即恢复为旧的x。当然,就像在编码中一样,这被认为有些混乱,因此通常可以通过为另一个变量选择一个不同的名称来避免这种情况。

令x如此……

  证明的东西

 新思想{让x成为其他事物……证明事物}得出新思想

 用x证明主要思想


19
我认为这真的很有用。可接受的答案几乎有点误导,因为它谈到了无法更改的价值,这根本不是问题letlet是关于范围的。
jinglesthula

只是一个想法:let在代码编写者的脑海中,让我想到了这样的事情:“好吧,就目前而言let foo = bar,但是然后它可以回到其原始值或不再是它的原始值。在区块范围和重新声明变量的例子这W3Schools的演讲let,同样,不是假装在某种形式的科学的答案带来的,但分享这更是一个记忆装置,记得当我想用let
阿兰·

为了概念上的清晰起见,我认为在这里值得更精确一些。您的示例ES6代码不会“忽略括号中的分配”。它按照指令对仅存在于该块中的变量toPrint执行赋值,然后在该块结束时将其完全丢掉。退出时,我们返回外部范围,而内部范围toPrint不再存在,因此console.log(toPrint)是指external toPrint。并不是任何事情都会被忽略,仅仅是let变量的作用域定义了有限的生存期。
FeRD

1
@FeRD,要点。我对上面的内容进行了修改,以消除“忽略”一词的用法,因为它混淆了这一点。
埃文·怀特

36

它确实var在范围上有所不同。现在它不能使用该名称,var因为该名称已经被使用。

因此,看起来它采用了具有最佳含义的次佳名称,该名称在一种有趣的英语结构中具有语义。

let myPet = 'dog';

用英语说“让我的宠物成为狗”


5
尽管let的起源可能是语言学和数学上的,但对于所有BASIC编程语言版本而言,最接近的引用无疑是LET语句,许多ES6的作者可能已经开始学习这种语言了。 40岁
17

5
@wide_eyed_pupil仅供参考:作为40岁以上(虽然不是ES6的作者),他在BASIC上长大,所以我所参与的社区中没有一个在常规实践中使用过LET。我们只是分配了变量,就像Python现在所做的那样(例如A$="HELLO WORLD")。涉及的解释器包括Rockwell AIM 65 BASIC,Atari Basic,CP / M上的MBASIC 5,Applesoft BASIC甚至是CP / M上的MS BASIC编译器BASCOM。我记得,VAX BASIC确实有LET,但没有要求。那时的内存非常紧张,每个语句的程序文本额外增加3或4个字符会有所不同,尤其是在“大型”程序中。
彼得·赫尔

@PeterHull有趣的是,我首先用数字CPU上的铅笔标记卡进行编码,然后在老人的研究实验室中使用大型机,然后在学校中使用Digital PDP8。从未见过人们在没有实际使用语句的情况下使用LET,在我所读过的书中也从未见过。提醒您,一旦我获得了任何好处,我就会被鼓励使用FORTRAN和PASCAL进行编码,而基本情况一样糟糕,甚至在我使用的版本中都没有GOSUB(即可重用函数)。
wide_eyed_pupil

您不能重新声明let变量。
CONvid19

10

最可能的可能性是它是最惯用的选择。不仅说起来容易,而且理解起来很直观。有些人甚至可以争论var

但是我认为这还有更多的历史。

维基百科

Dana Scott的LCF语言是lambda演算向现代功能语言演变的阶段。该语言引入了let表达式,该表达式自那时以来已出现在大多数功能语言中。

诸如ALGOL和Pascal之类的全状态命令式语言本质上实现了let表达式,以在块结构中实现有限的功能范围。

我想也相信这对于letJavascript 也是一个启发。


这个答案是指lambda演算的“ let expression”,这也许不是OP所要求的。它似乎比LET1964
。– Joseph Quinsey

整篇文章是Wikipedia用户Thepigdog在2014年基本上单手撰写的几篇文章之一。我很明智,只是说它们都是从非常狭窄的角度撰写的,因此引用的(完全未引用)声明应该是解释为说Scott的论文 ES6引入letJavaScript 的相同方式将let表达式“引入”了lambda演算。就目前而言,这并非完全不真实,但没有任何实际意义。(而不以任何方式排除Scott的“ let”的使用受到BASIC启发的可能性LET。)
FeRD

1

Let使用更直接的块级限制范围,而var通常是函数范围或全局范围。

似乎最有可能选择let,因为在许多其他语言中都可以找到let来定义变量,例如BASIC和许多其他语言。


1

我认为JavaScript对Scheme的负债在这里很明显。Scheme不仅具有let,而且具有let *,let *-值,let语法和let-values。(请参见《方案编程语言》,第四版)。

((这种选择进一步增强了JavaScript是Lispy的概念的可信度,但在我们被迷住之前,不是谐音。)))


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.