JavaScript关闭在哪里? [英] Where does a JavaScript closure live?

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

问题描述

我写了这段代码来自学JavaScript关闭:

I wrote this code to teach myself about JavaScript closures:

function1 = function(){
  var variable = "foo"
  var function2 = function(argument){
    console.log(variable + argument);
  }
  return function2
}

function3 = function1();
function3("bar");

按预期打印foobar。但变量在哪里?

This prints "foobar" as expected. But where does the variable live?

它是否成为function3的属性,还是存储在function3中的其他位置? JavaScript是否遍历某种闭包链,类似于它如何遍历原型链?它存储在其他地方的内存中吗?

Does it become a property of function3, or stored somewhere else in function3? Does JavaScript traverse some kind of closure chain, similarly to how it traverses the prototype chain? Is it stored in memory somewhere else?

我试图更深入地理解这一点。

I am trying to understand this more deeply.

推荐答案

tl; dr:


变量在哪里?

where does the variable live?

在它定义的环境中。


它成为function3的属性,还是存储在function3的其他地方?

Does it become a property of function3, or stored somewhere else in function3?

No。


JavaScript是否遍历某种闭包链,类似于它如何遍历原型链?

Does JavaScript traverse some kind of closure chain, similarly to how it traverses the prototype chain?

是。


它是否存储在其他地方的内存中?

Is it stored in memory somewhere else?

是。

tl; dr 2:

函数保持对它们所创建的环境的引用。当调用函数时,它会创建一个新的环境,其父级是环境该功能保留了参考。

Functions keep a reference to the environment they are created in. When a function is called it creates a new environment whose parent is the environment the function kept the reference to.

更长的解释:

每当执行一个函数时,新的 词汇环境 已创建。环境有两个字段: 环境记录 ,其中所有变量都被跟踪,外部词汇环境,顾名思义,引用父词汇环境。

Whenever a function is executed a new lexical environment is created. The environment has two "fields": an environment record where all the variables are being tracked and a outer lexical environment that refers to, as the name suggested, to the "parent lexical environment".

因此,当我们评估您的代码示例时,内存的初始状态(在执行任何操作之前)可能看起来像这样(简化):

So when we your code example is evaluated, the initial state of the memory (before executing anything) might look like this (simplified):

+-(Global) lexical environment-+     +-Environment Record-+
+-------------+----------------+     +---------+----------+
| Environment |       *--------+---> |function1|undefined |
|   Record    |                |     +---------+----------+
+-------------+----------------+     |function3|undefined |
|    Outer    |                |     +---------+----------+
|   lexical   |    (empty)     |
| environment |                |
+-------------+----------------+

全球环境没有任何外部环境,因为它位于顶部。 function1 function3 是两个尚未初始化的绑定(尚未评估作业)。

The global environment doesn't have any outer environment because it is at the top. function1 and function3 are two bindings that haven't been initialized yet (the assignment wasn't evaluated yet).

创建函数(评估 function1 = function(){...} )后,内存看起来像这样:

After creating the function (evaluating function1 = function() { ... }), the memory looks like this:

            +------------------------------------------------------------------------+
            |                                                                        |
            v                                                                        |
+-(Global) lexical environment-+    +-Environment Record-+     +-----Function Object-+---+
+-------------+----------------+    +---------+----------+     +---------------+-----+---+
| Environment |       *--------+--->|function1|    *-----+---->|[[Environment]]|     *   |
|   Record    |                |    +---------+----------+     +---------------+---------+
+-------------+----------------+    |function3|undefined |     |     name      |function1|
|    Outer    |                |    +---------+----------+     +---------------+---------+
|   lexical   |    (empty)     |
| environment |                |
+-------------+----------------+

现在 function1 有一个值,一个函数对象。函数对象具有多个内部(例如 [[Environment]] )和外部(例如 name )属性。顾名思义,无法从用户代码访问内部属性。 [[Environment]] 属性非常重要。注意它是如何引用函数创建的词法环境的!

Now function1 has a value, a function object. Function objects have multiple internal (e.g. [[Environment]]) and external (e.g. name) properties. As the name implies, internal properties cannot be accessed from user code. The [[Environment]] property is very important. Notice how it refers back to the lexical environment the function was created in!

下一步是执行 function3 = function1(),即调用 function2 。正如我在一开始所说,每当执行一个函数时,都会创建一个新的词法环境。让我们在进入函数后查看内存:

The next step is executing function3 = function1(), i.e. calling function2. As I said at the very beginning, whenever a function is executed a new lexical environment is created. Let's look at the memory just after entering the function:

               +------------------------------------------------------------------------+
               |                                                                        |
               v                                                                        |
   +-(Global) lexical environment-+    +-Environment Record-+     +-----Function Object-+---+
   +-------------+----------------+    +---------+----------+     +---------------+-----+---+
   | Environment |       *--------+--->|function1|          +---->|[[Environment]]|     *   |
   |   Record    |                |    +---------+----------+     +---------------+---------+
+> +-------------+----------------+    |function3|undefined |     |     name      |function1|
|  |    Outer    |                |    +---------+----------+     +---------------+---------+
|  |   lexical   |    (empty)     |
|  | environment |                |
|  +-------------+----------------+
|
|
|
|  +-----lexical environment------+    +-Environment Record-+
|  +-------------+----------------+    +---------+----------+
|  | Environment |       *--------+--->|variable |undefined |
|  |   Record    |                |    +---------+----------+
|  +-------------+----------------+    |function2|undefined |
|  |    Outer    |                |    +---------+----------+
|  |   lexical   |        *       |
|  | environment |        |       |
|  +-------------+--------+-------+
|                         |
+-------------------------+

这看起来非常类似于全球环境的结构!我们有一个词法环境,其环境记录包含两个未初始化的绑定。但现在最大的不同是外部词汇环境指向全球词汇环境。这怎么可能?

This looks very similar to the structure of the global environment! We have a lexical environment that has an environment record with two unintialized bindings. But the big difference now is that "outer lexical environment" points to the global lexical environment. How is that possible?

当调用 function1 并创建一个新的词法环境时,我们设置新的值环境外部词汇环境字段的值为 function1 [[Environment]] 字段。这是范围链的创建。

When calling function1 and creating a new lexical environment, we set the value of the new environments "outer lexical environment" field to the value of function1's [[Environment]] field. This is were the scope chain is created.

现在,在执行 function1 之后,内存具有以下结构:

Now, after executing function1, the memory has this structure:

               +------------------------------------------------------------------------+
               |                                                                        |
               v                                                                        |
   +-(Global) lexical environment-+    +-Environment Record-+     +-----Function Object-+---+
   +-------------+----------------+    +---------+----------+     +---------------+-----+---+
   | Environment |       *--------+--->|function1|    *-----+---->|[[Environment]]|     *   |
   |   Record    |                |    +---------+----------+     +---------------+---------+
+> +-------------+----------------+    |function3|   |      |     |     name      |function1|
|  |    Outer    |                |    +---------+---+------+     +---------------+---------+
|  |   lexical   |    (empty)     |                  |
|  | environment |                |                  |
|  +-------------+----------------+                  +-------------------------+
|                                                                              |
|             +----------------------------------------------------------------+--------+
|             v                                                                |        |
|  +-----lexical environment------+    +-Environment Record-+                  v        |
|  +-------------+----------------+    +---------+----------+                           |
|  | Environment |       *--------+--->|variable |  'foo'   |     +-----Function Object-+---+
|  |   Record    |                |    +---------+----------+     +---------------+-----+---+
|  +-------------+----------------+    |function2|    *-----+---->|[[Environment]]|     *   |
|  |    Outer    |                |    +---------+----------+     +---------------+---------+
|  |   lexical   |        *       |                               |     name      |function2|
|  | environment |        |       |                               +---------------+---------+
|  +-------------+--------+-------+
|                         |
+-------------------------+

类似于 function1 function2 引用了通过调用创建的环境函数2 。另外, function3 是指我们创建的函数,因为我们从 function1 返回它。

Similar like function1, function2 has a reference to the environment created by calling function2. In addition, function3 refers to the function we created because we return it from function1.

最后一步:致电 function3('bar')

               +------------------------------------------------------------------------+
               |                                                                        |
               v                                                                        |
   +-(Global) lexical environment-+    +-Environment Record-+     +-----Function Object-+---+
   +-------------+----------------+    +---------+----------+     +---------------+-----+---+
   | Environment |       *--------+--->|function1|    *-----+---->|[[Environment]]|     *   |
   |   Record    |                |    +---------+----------+     +---------------+---------+
+> +-------------+----------------+    |function3|   |      |     |     name      |function1|
|  |    Outer    |                |    +---------+---+------+     +---------------+---------+
|  |   lexical   |    (empty)     |                  |
|  | environment |                |                  |
|  +-------------+----------------+                  +-------------------------+
|                                                                              |
|             +----------------------------------------------------------------+--------+
|             v                                                                |        |
|  +-----lexical environment------+    +-Environment Record-+                  v        |
|  +-------------+----------------+    +---------+----------+                           |
|  | Environment |       *--------+--->|variable |  'foo'   |     +-----Function Object-+---+
|  |   Record    |                |    +---------+----------+     +---------------+-----+---+
|+>+-------------+----------------+    |function2|    *-----+---->|[[Environment]]|     *   |
|| |    Outer    |                |    +---------+----------+     +---------------+---------+
|| |   lexical   |        *       |                               |     name      |function2|
|| | environment |        |       |                               +---------------+---------+
|| +-------------+--------+-------+
++------------------------+
 |
 | +-----lexical environment------+    +-Environment Record-+
 | +-------------+----------------+    +---------+----------+
 | | Environment |       *--------+--->|argument |  'bar'   |
 | |   Record    |                |    +---------+----------+
 | +-------------+----------------+
 | |    Outer    |                |
 | |   lexical   |        *       |
 | | environment |        |       |
 | +-------------+--------+-------+
 +------------------------+

此处类似,创建了一个新环境它的外部词汇环境字段指向调用 function1 时创建的环境。

Similar here, a new environment is created and its "outer lexical environment" field points to the environment created when function1 was called.

现在,查找值参数很简单,因为它存在于环境自己的记录中。但是当查找变量时,会发生以下情况:由于它在环境自己的记录中不存在,因此它会查看其外部词汇环境的记录。它可以做到这一点,因为它有一个参考。

Now, looking up the value of argument is straightforward, because it exists in the environment's own record. But when looking up variable, the following happens: Since it doesn't exist in the environment's own record, it looks at its "outer lexical environment"'s record. It can do that because it has a reference to it.

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

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