【问题标题】:Why was block scope not originally implemented in JavaScript?为什么块作用域最初没有在 JavaScript 中实现?
【发布时间】:2013-06-26 04:42:48
【问题描述】:

我已经阅读并通过自己的经验发现,JavaScript 没有块作用域。假设这种语言是出于某种原因设计的,你能向我解释一下是什么原因吗?

我在 Google 和这里​​查看过,但我发现的帖子只是重申 JS 具有函数作用域而不是块作用域,而没有解释原因。我很想知道为什么会这样。

【问题讨论】:

  • JavaScript 中的函数式编程风格并不鼓励它,我想再加上 JS 是一个仓促的概念,但 let 即将出现在 ES6 中,因此我们将在不久的将来拥有块范围。 Firefox 已经支持let
  • 语言的创始人回答了这个问题,@Aadit 和我自己的解释似乎涵盖了任何其他问题,所以我认为它不再只是意见。

标签: javascript scope


【解决方案1】:

将我的评论转换为答案

创作者的选择:我在 Brendan 上发了推文并得到了following answer

@mplungjan 10 天没有为块范围留出时间。此外,90 年代中期的许多“脚本语言”范围很小,后来发展得更多。


也就是说,这里有一些相关点:

重要提示:ECMAScript2015(第 6 版)之前的 JavaScript 没有块作用域。块中引入的变量的作用域是包含函数或脚本,设置它们的效果会持续到块本身之外。换句话说,块语句不引入范围。尽管“独立”块是有效的语法,但您不想在 JavaScript 中使用独立块,因为如果您认为它们在 C 或 Java 中执行类似块的操作,它们不会按照您的想法执行。

我们可以通过创建新函数并立即调用它们来人为地引入作用域

letconst 声明的变量被提升,但它们初始化为 undefined,方式与 var 相同。因此,在赋值之前引用 letconst 声明的变量会引发 ReferenceError。

在同一块范围内重新声明同一变量会引发 SyntaxError。

【讨论】:

【解决方案2】:

截至 2015 年的新答案。ES6 确实具有使用 letconst 关键字定义变量的块范围。

【讨论】:

  • 不幸的是,有些用户可能还生活在 2010 年,因此依赖全新的语言功能并不是最佳做法。
  • @riv - Javascript 不仅用于浏览器,您必须按照最低公分母进行编码。它可以在 node.js 等环境中使用,您可以在其中控制整个执行环境,现在可以使用let。或者,您可以使用一种转译器,让您在 ES6 中编写代码,然后转译器将其转换为 ES5 兼容代码,以便在旧版浏览器中运行。
  • 不是一个新的答案,因为 Js 具有来自 ES3try/catch 块范围
  • @Trung - 你能提供一个解释这个的参考吗?我没有看到任何变量定义块作用域的证据。
  • @Trung - 这是一个非常特殊的情况(仅在 catch 处理程序中,这不太可能是 OP 所要求的,并且不能以任何通用方式用于创建您自己的块范围变量在 ES3 中的常规块中。如果您认为这回答了 OP 的问题,请随意做出自己的答案。
【解决方案3】:

由于以下原因未实现块范围:

  1. 它使语言更易于实现。 JavaScript 最初被设计为一种用于编写交互式 Web 应用程序的语言。因此,它需要小巧且易于实施。
  2. 块作用域会影响 JavaScript 等动态语言的性能。这是因为当您尝试访问不在当前作用域中的某个变量时,JavaScript 首先检查当前作用域,然后检查父作用域,依此类推,直到找到变量或到达末尾。因此,块作用域的引入会使循环和嵌套循环中的变量访问变得非常缓慢。
  3. 缺少块作用域使编写程序更容易。例如,假设您只想在某个条件为真时创建一个变量。在 JavaScript 中您需要做的就是在 if 语句中声明和定义变量。在像 C 这样的语言中,您必须在 if 语句之外声明变量并在 if 语句中定义它。
  4. 缺少块作用域允许提升声明。这在函数声明的情况下特别有用。例如,请参阅此小提琴:http://jsfiddle.net/L6SgM/(但请注意,此示例在 Firefox 中不起作用)。
  5. 由于 JavaScript 支持一流的函数表达式,我们不需要块作用域。可以使用immediately invoked function expressions 模拟它们。

【讨论】:

  • “块作用域给 JavaScript 等动态语言带来了性能损失。” -- 这是实现的属性,而不是语言。也许它适用于第一个 JavaScript 实现,但过去十年编写的任何引擎都不应该受到它的影响。
  • #5) 严格来说,我们并不“需要”块作用域,就像我们一开始就需要 JavaScript 一样……谢天谢地,ECMA 团队似乎不同意通过添加对块作用域的支持'let' 关键字...更简单的语言结构总是受欢迎的。
  • I :您能否提供证明 Brendan Eich 没有在 Javascript 中实现块作用域的来源,原因有您提到的 5 个?我怀疑您将历史原因 (#1) 与您的原因 (#2 to #5) 混为一谈。 . . II:#3 错误:变量总是被创建,只有它的初始化是有条件的(参见:jsfiddle.net/paercebal/yvwhu7r0)。 #4 是假的(在 Chrome 中添加 "use strict" ; 会出现错误:Uncaught SyntaxError: In strict mode code, functions can only be declared at top level or immediately within another function.)。 #5是一个肮脏的解决方法。 . . .
  • 它可能使编写程序更容易,但肯定不会维护它们。
【解决方案4】:

有很多原因,但我想到的一些原因是帮助解析/调试使用对象文字(有时看起来像块)的代码,并简化局部变量的垃圾收集。

我希望承诺的支持(在此讨论,例如 http://esdiscuss.org/notes/2012-07-25)最终成为现实,因为使用像 i 这样的变量非常方便,这些变量仅在单个循环中是本地的。

【讨论】:

    猜你喜欢
    • 2018-10-26
    • 1970-01-01
    • 1970-01-01
    • 2021-09-03
    • 2021-04-09
    • 2011-06-21
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    相关资源
    最近更新 更多