关闭和ES2015 [英] Closures and ES2015

查看:133
本文介绍了关闭和ES2015的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于另一个关闭问题,我提前道歉,但我想澄清一下我对JavaScript中实现闭包方式的理解。



考虑以下代码:

  01'use strict'; 
02 function foo(){}
03 foo();

我已经建立了一个问题。 p>

直到 foo 在第3行没有被调用时,不会创建相应的执行上下文。



所以只要我可以从规范中得知,评估这个代码时:


  1. 每个执行上下文都有一个LexicalEnvironment组件,用于解析由其中的代码进行的标识符引用(8.3,表23)。

  2. FunctionCreate 将引用(命名为scope)传递给当前执行上下文的LexicalEnvironment组件。 (14.1.19)

  3. FunctionCreate 调用 FunctionInitialize 传递scope( 9.2.5)

  4. FunctionInitialize 确保功能的内部插槽 [[Environment]] 被创建的对象设置为范围的值(对当前执行上下文的LexicalEnvironment组件的引用)(9.2.4)

最后,当 foo 实际被调用时,我发现规格更难解释。


  1. PrepareForOrdinaryCall 中,调用新执行上下文的LexicalEnvironment被设置为调用 NewFunctionEnvironment (9.2.1.1)

  2. NewFunctionEnvironment 复制对外部执行上下文的LexicalEnvironment组件的引用( [[Environment]] 功能对象的插槽)插入环境记录( EnvironmentRecord ?)的Lex作为外部词汇环境参考(8.1.2.4)的执行上下文的icalEnvironment组件

因此,关闭在一个两步的方式:


  1. 函数对象与封闭执行上下文的LexicalEnvironment的关联是在函数 - 对象实例化时间。这是功能对象的内部插槽。

  2. 当调用函数时,这个引用包含LexicalEnvironment组件的外部执行上下文(函数对象 [[Environment]]的内容)被复制到规范不精确定义的(?)/ EnvironmentRecord (?)子组件。

这个声音是否正确

解决方案


这个声音是否正确?




很多。我只是不会使用复制的工作,而是链接。为了简化一下:


  1. 当创建一个函数时,它存储是对创建它的环境的引用。

  2. 执行该功能时,此存储环境将成为新创建的函数环境的外部环境。

或图片:

  + ------------ ---- + + ---------------- + 
函数| | [[环境]] |外面|
创建|函数| --------------------> |环境|
| | | |
+ ---------------- + + ---------------- +
^
|
|
+ ---------------- + |
函数|功能|外部环境参考|
执行|环境| ------------------------------ +
| |
+ ---------------- +

这发生在每个函数中,并且根据你对闭包 1 的定义,这使得每个函数都被关闭(或不)。






1:我相信这两个函数需要关闭一个函数的含义:




  • 如果函数存储对其创建的环境的引用,则它是一个闭包(适用于JS中的每个函数)

  • 如果函数存储引用它在中创建的环境留下该环境(环境不再存在),它是一个关闭。这当然不是这样。


I apologize in advance for yet another closure question, but I'd like to clarify my understanding of the way closures are implemented in JavaScript.

Consider the following code:

01 'use strict';
02 function foo() {}
03 foo();

I have established in a question earlier in the year that a closure is conceptually (if not actually due to engine optimizations) created here.

And until foo is not invoked on line 3 a corresponding execution context is not created.

So as far as I can tell from the spec, when evaluating this code:

  1. Each execution context has a "LexicalEnvironment" component used to resolve identifier references made by code within it (8.3, Table 23).
  2. FunctionCreate is called, passing in a reference (named "scope") to the "LexicalEnvironment" component of the current execution context. (14.1.19)
  3. FunctionCreate calls FunctionInitialize passing "scope" (9.2.5)
  4. FunctionInitialize ensures that the [[Environment]] internal slot of the function-object being created is set to the value of "scope" (the reference to the "LexicalEnvironment" component of the current execution context) (9.2.4)

Finally, when foo is actually invoked, I find the spec harder to interpret.

  1. In PrepareForOrdinaryCall, the "LexicalEnvironment" of the new execution context for the call is set to be the result of calling NewFunctionEnvironment (9.2.1.1)
  2. NewFunctionEnvironment copies the reference to the "LexicalEnvironment" component of the outer execution context (the [[Environment]] slot of the function-object) into the Environment record (EnvironmentRecord?) of the "LexicalEnvironment" component of the execution context under construction as the "outer lexical environment reference" (8.1.2.4)

Thus closures are implemented in a two step fashion:

  1. A linkage between function-object and the enclosing "LexicalEnvironment" of the enclosing execution context, is created at function-object instantiation time. This is the [[Environment]] internal slot of the function-object.
  2. When a function is invoked, this reference to the enclosing "LexicalEnvironment" component of the outer execution context (the contents of the [[Environment]] slot of the function object) is copied into a spec-imprecisely-defined(?)/EnvironmentRecord(?) sub-component of the "LexicalEnvironment" component of the new execution context.

Does this sound about right?

解决方案

Does this sound about right?

Pretty much. I just wouldn't use the work "copied", rather "linked". To simplify it a little:

  1. When a function is created, it stores are reference to the environment it was created it.
  2. When the function is executed, this stored environment becomes the "outer environment" of the newly created function environment.

Or in pictures:

                  +----------------+                     +----------------+
   Function       |                |   [[Environment]]   |     Outer      |
   creation       |    Function    |-------------------->|  Environment   |
                  |                |                     |                |
                  +----------------+                     +----------------+
                                                                  ^        
                                                                  |        
                                                                  |        
                  +----------------+                              |        
   Function       |    Function    |  outer environment reference |        
   execution      |  Environment   |------------------------------+        
                  |                |                                       
                  +----------------+                                       

This happens to every function and depending on your definition of closure1, this makes every function a closure (or not).


1: I believe there are these two takes on what it means for a function to be a closure:

  • If a function stores a references to the environment it was created in, it's a closure (applies to every function in JS)
  • If a function stores a reference to the environment it was created in and "leaves" that environment (the environment "ceases to exist"), it's a closure. That's of course not always the case.

这篇关于关闭和ES2015的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆