【问题标题】:Why variable object was changed to lexical environment in ES5?为什么在 ES5 中将变量对象更改为词法环境?
【发布时间】:2017-03-25 11:47:04
【问题描述】:

ES5 将 variable object(VO) 更改为词法环境。 VO 作为感知已经很明显了,这种变化的动机是什么?

【问题讨论】:

  • 我不明白这个问题? variable object 是什么意思?您能否参考您正在谈论的规范更改?
  • @nils 添加了链接。
  • @MadaraUchiha 有趣的是,ES3 规范实际上确实使用了术语variable object:ecma-international.org/publications/files/ECMA-ST-ARCH/…(第 10.1.3 节)
  • 我认为在推特上向 Brendan Eich 或 Allen Wirfs-Brock 提问是一个很好的问题,然后在此处写下答案。

标签: javascript ecmascript-5 lexical-scope ecmascript-3


【解决方案1】:

您链接的 ES3 文章的同一位作者也写了关于 ES5 的文章(甚至在那里链接了该部分)。我会从他的"Declarative environment record" section in ECMA-262-5 in detail. Chapter 3.2. Lexical environments: ECMAScript implementation 引用 Soshnikov 先生的话:

在一般情况下,声明性记录的绑定被假定直接存储在实现的低级别(例如,在虚拟机的寄存器中,从而提供快速访问)。这是与 ES3 中使用的旧 激活对象 概念的主要区别。

也就是说,规范不要求(甚至间接不推荐)将声明性记录实现为简单的对象,在这种情况下效率低。这一事实的结果是声明性环境记录不假定直接暴露给用户级别,这意味着我们无法访问这些绑定,例如记录的属性。实际上,我们以前也做不到,即使在 ES3 中 - activation object 也对用户直接不可访问(尽管 Rhino 实现通过 __parent__ 暴露了它除外)属性)。

潜在地,声明性记录允许使用完整的lexical addressing 技术,即无需任何范围链查找即可直接访问所需的变量——无论嵌套范围的深度如何(如果存储是固定且不可更改的,则所有变量即使在编译时也可以知道地址)。然而,ES5 规范并没有直接提到这个事实。

因此,我们应该再次理解为什么需要用 声明性环境记录 替换旧的激活对象 概念的主要内容是实施的效率

因此,正如 Brendan Eich 也 mentioned(最后一段)——ES3 中的激活对象实现只是一个“错误”:“我会注意到 ES5 中有一些真正的改进,特别是第 10 章现在使用声明性绑定环境。 ES1-3 对范围对象的滥用(我再次责备我在 1995 年在 JS 中这样做,急需实现语言所需的对象)是一个错误,而不是一个特性。”

我认为我无法更好地表达这一点。

【讨论】:

  • 我也想过这样的事情。但是,即使规范使用了对象,如果可观察的行为相同,实现也可以使用他们想要的任何底层数据结构,不是吗?
  • @Oriol 是的,我想他们可以,但它并不适合,因为记录具有静态形状(这是 imo 最重要的区别)。然后是您在答案中提到的创建与初始化,而且查找/分配的工作方式也大不相同(原型与范围链)。
【解决方案2】:

我认为变量对象更类似于environment records

环境记录记录了创建的标识符绑定 在其相关词汇环境的范围内。

在 ES5 中有两种不同的环境记录:

声明性环境记录用于定义效果 FunctionDeclarations 等 ECMAScript 语言语法元素, VariableDeclarationsCatch 子句直接将标识符绑定与 ECMAScript 语言值相关联。目的 环境记录用于定义 ECMAScript 的效果 关联的元素,例如 ProgramWithStatement 标识符与某些对象的属性绑定。

所以问题是为什么要引入声明性环境记录,而不是像 ES3 变量对象那样仅使用对象环境记录。不同之处在于declarative environment records 可以有不可变的绑定:

除了所有环境支持的可变绑定 记录,声明性环境记录也提供不可变的 绑定。一个不可变的绑定是其中一个之间的关联 标识符和值一旦被修改就不能被修改 成立。

不可变绑定在对象中没有直接等价物。一个属性可以定义为不可配置和不可写,变成不可变的。然而,

不可变绑定的创建和初始化是不同的步骤,因此 这种绑定可能存在于初始化或 未初始化状态。

但是你不能有一个未初始化的属性。如果你用 undefined 值定义了一个不可配置的不可写属性,那么你将无法将它初始化为所需的值。

我认为在 ES5 中不可能有未初始化的不可变绑定。 CreateImmutableBinding 仅在Declaration Binding InstantiationFunction Definition 中使用,并且在这两种情况下都会立即使用 InitializeImmutableBinding 进行初始化。

但这样做可能是为了允许未初始化的不可变绑定作为语言的扩展,例如 JavaScript 1.5 const。或者他们可能已经想到了 ES6 const

【讨论】:

    猜你喜欢
    • 2019-04-24
    • 1970-01-01
    • 1970-01-01
    • 2017-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-01
    相关资源
    最近更新 更多