Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
347 views
in Technique[技术] by (71.8m points)

javascript - Closures and ES2015

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 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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...