为什么在JavaScript中用于块级作用域变量声明的名称选择了“let”?

367

我理解为什么var叫这个名字——因为它是变量,const——因为它是常量,但是let的名字背后有什么含义呢?而且let的作用域只在当前代码块内。是让它成为吗?


12
BASIC是一种编程语言,发明于1962年,使用关键字“LET”。可能存在更早的编程语言示例。 - David R Tribble
9
BASIC 是在 1964 年发明的,而不是 1962 年。有关详细信息,请参见此处。"LET" 的用法在手册第一版草稿的第7页描述,该手册于1964年5月发布,PDF 可在此处找到。 - Joseph Quinsey
更具体地说,'const' 是一个常量或不可变(只读)对象引用,而对象本身仍然是可变的。例如,在声明/分配'const foo = ['bar']'之后,'foo.push('bat')'仍然是合法的,但'foo = ['bar', 'bat']'则不是。但这太麻烦了。 - user982671
这不就是英语动词“let”(例如,“let it be so”)吗?为什么会有疑问呢? - 2540625
1
耶,又来了一个没有人要求或需要的功能。使用IIFE可以得到相同的效果。Javascript在15年前已经做到了它需要做的事情,现在他们只是为了毫无意义地与最新和最伟大的关键字和结构竞争。个人喜欢的包括在所谓的原型对象模型中使用类结构。严格类型和可选类型什么时候才能来呢? - Christoffer Bubach
1
@ChristofferBubach 嗯,我们有TypeScript来处理严格类型的JavaScript... - Gwyneth Llewelyn
8个回答

427

let是一个数学语句,早期的编程语言如Scheme和Basic采用了这种语句。变量被认为是低级实体,不适合于更高层次的抽象,因此许多语言设计者希望引入类似但更强大的概念,例如Clojure、F#和Scala中的let,它可能表示一个值,或者是一个可以赋值但不能更改的变量,从而让编译器能够更好地捕获编程错误并优化代码。

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


123
官方 Mozilla 文档页面引用了这个页面来回答这个问题:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/let - Sarath Chandra
11
len('var') === len('let') 也很好,这意味着你在编辑器中以任一方式声明变量时,它们的长度都会对齐。我尚未发现有什么迹象表明这是有意为之的,但这既可以让代码更加美观易读,也可能在混用两者时导致极其烦人的调试问题(这本来就不是个好主意,但我曾见过这样的情况发生)。 - brichins
18
换句话说,“let”一直被用来描述常量,比如“let C = 光速”,因此Javascript决定使用“let”来描述具有非标准作用域的变量,并同时引入另一个关键字来表示常量。 - fijiaaron
7
非标准作用域是什么?整个函数的作用域不受你声明它的块的影响,这种方式不是有点奇怪吗? - SamB
6
@fijiaaron,你在这里是错误的。在科学中,这不是“let”的好用法,因为那些变量每个人都知道,通常不会用它来表示常量。c就是光速,我们不必“让”它成为光速。当距离到中心不是一个常量时,我们会说“让x为距离到中心”。 - Nacht
显示剩余9条评论

110

我想这符合数学传统。在数学中,通常会说“假设x是任意实数”之类的话。


5
我更喜欢这个答案,因为它简洁易懂且与我们都学过代数有关。接下来可能需要跟进解释,类似其他人所指出的那样。 - duduwe
你猜呢?有一个更好(改进)的答案会更好。 - carloswm85
3
@carloswm85 我想确实很不错。 - Tigran Saluev

81

除了exebook的回答之外,关键字let在数学上的使用也很好地封装了在Javascript/ES6中使用let时的作用域影响。特别是,正如以下ES6代码在打印'Hello World'的值时,不知道toPrint括号中的赋值

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

Let在形式化数学中(尤其是证明的写作中)表示当前变量仅存在于该逻辑思想的范围内。在下面的例子中,x一进入新的概念(通常这些是证明主要思想所必需的概念),就立即获得了一个新的身份,并在子证明结束时立即恢复到旧的x。当然,就像在编码中一样,这被认为有点令人困惑,因此通常通过选择其他名称来避免使用另一个变量的名称。

设x是这样那样的...

 证明内容

 新思路{设x是其他的东西...证明某些东西} 结束新思路

 用旧x证明主要思想


22
我认为这非常有用。被接受的答案有点误导,因为它谈论到值无法更改,而这并不是 let 的全部意思。let 关注于作用域。 - jinglesthula
1
只是一个想法:let 让我想到代码编写者脑海中正在发生的事情,"好的,就在这一刻,let foo = bar,但它随后可以回到原始值或停止存在。这在 W3Schools 的 let 展示 中的块级作用域和重新声明变量的示例中得到了很好的说明。再次强调,这不是要提供某种科学答案,而是作为记忆 let 时的助记符。 - Alain
1
我认为在这里稍微更加精确一些是值得的,出于概念上的明晰起见。你的ES6代码示例并不是“忽略了花括号中的指派”。它按照指示执行了赋值操作,_在块范围内创建了一个名为 toPrint新变量_,然后当块结束时,将该变量扔掉。退出时,我们回到了外部作用域,在那里内部的 toPrint 不再存在,因此 console.log(toPrint) 引用的是 外部 toPrint。并非有什么被忽略了,只是 let 变量具有由其作用域定义的有限生命周期。 - FeRD
1
@FeRD,非常好的观点。我对上面的内容进行了编辑,删除了“忽略”一词的使用,因为它会混淆重点。 - Evan Brooks

40

它与var所做的事情完全相同,只是范围不同。现在它不能采用var这个名称,因为它已经被占用了。

因此,看起来它采用了下一个最好的名称,该名称在一个有趣的英语语言结构中具有语义。

let myPet = 'dog';

用英文说是“让我的宠物变成一只狗”


7
虽然“let”一词的起源可能是语言学和数学上的,但它最为通俗易懂的参考就是 BASIC 编程语言中所有版本中的 LET 语句。如果 ES6 的作者们年龄超过40岁,他们很可能从学习 LET 语句开始编程。 - wide_eyed_pupil
8
@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个额外的字符在程序文本中会有所不同,尤其是在“大”程序中。 - Peter Hull
@PeterHull 很有趣,我第一次编码是在附着于数字CPU的铅笔标记卡上进行的,然后是在老人研究实验室的大型机和学校的Digital PDP8上。从未见过人们在没有实际使用语句的情况下使用LET,即使在我读的书中也没有。当然,我被鼓励尽早使用FORTRAN和PASCAL编码,因为基本语言太糟糕了,在我使用的版本中甚至没有GOSUB(即可重用函数)。 - wide_eyed_pupil
1
你不能重新声明一个 let 变量。 - Pedro Lobito

11
最有可能的可能性是这是最惯用的选择。它不仅易于发音,而且相当直观易懂。有些人甚至可以争论说,比 var 更加易懂。
但我认为这背后还有更多历史。
来自 Wikipedia
Dana Scott 的 LCF 语言是 lambda 演算进化为现代函数式语言的一个阶段。该语言引入了 let 表达式,自那时以来,大多数函数式语言都出现了这种表达式。
像 ALGOL 和 Pascal 这样的状态型命令式语言实际上实现了 let 表达式,以实现函数的受限作用域,在块结构中。
我想相信这也是 Javascript 中 let 的灵感来源。

这个答案涉及到lambda演算中的“let表达式”,可能不是OP所问的。而且它似乎比BASIC中的“LET”晚,1964年才出现。 - Joseph Quinsey
1
整篇文章基本上是由维基百科用户Thepigdog在2014年独自撰写的几篇文章之一。我会审慎地说,它们都是从非常狭窄的角度来写的,因此所引用的(完全没有参考文献的)声明应该被解释为说Scott的论文“引入”了let表达式“到lambda演算”,就像ES6将let引入JavaScript一样。就其本身而言,这并不完全不真实,但也没有任何真正的意义。(并且并不排除Scott使用“let”的灵感也受到BASIC LET的影响的可能性。) - FeRD

3

它也可能意味着 "词法环境类型或绑定"。仅仅是让“这个”成为“那个”使我感到困扰。在 lambda 演算中,let rec 没有意义。


1
我也在寻找这样的答案,我怀疑它是否具有“让”的普通英语含义。 - Meenohara

1
我认为JavaScript对Scheme的借鉴是显而易见的。Scheme不仅有let,还有let*,let*-values,let-syntax和let-values。(参见,《Scheme编程语言》第4版)。
(这个选择进一步证明了JavaScript是Lispy的概念,但在我们陷入其中之前,请注意,它并不是同像的。)

1

let关键字用于更直接的块级限定作用域,而var通常是函数作用域或全局作用域。

看起来let被选择最有可能是因为它在许多其他语言中都被用来定义变量,例如BASIC和许多其他语言。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接