Wyl*_*udd 27 javascript closures
我写了这段代码来自学JavaScript关闭:
function1 = function(){
var variable = "foo"
var function2 = function(argument){
console.log(variable + argument);
}
return function2
}
function3 = function1();
function3("bar");
Run Code Online (Sandbox Code Playgroud)
按预期打印"foobar".但变量在哪里生活?
它是否成为function3的属性,还是存储在function3中的其他位置?JavaScript是否遍历某种闭包链,类似于它如何遍历原型链?它存储在其他地方的内存中吗?
我想更深入地了解这一点.
Fel*_*ing 32
TL;博士:
变量在哪里生活?
在它所定义的环境中.
它是否成为function3的属性,还是存储在function3中的其他位置?
没有.
JavaScript是否遍历某种闭包链,类似于它如何遍历原型链?
是.
它存储在其他地方的内存中吗?
是.
tl;博士2:
函数保留对它们所创建的环境的引用.当调用函数时,它创建一个新的环境,其父级是函数保留引用的环境.
更长的解释:
每当执行一个函数时,都会创建一个新的词法环境.环境有两个"字段":一个环境记录,其中所有变量都被跟踪,外部词汇环境,如名称所示,指向"父词法环境".
因此,当我们评估您的代码示例时,内存的初始状态(在执行任何操作之前)可能看起来像这样(简化):
+-(Global) lexical environment-+ +-Environment Record-+
+-------------+----------------+ +---------+----------+
| Environment | *--------+---> |function1|undefined |
| Record | | +---------+----------+
+-------------+----------------+ |function3|undefined |
| Outer | | +---------+----------+
| lexical | (empty) |
| environment | |
+-------------+----------------+
Run Code Online (Sandbox Code Playgroud)
全球环境没有任何外部环境,因为它处于最顶层.function1
并且function3
是尚未初始化(分配尚未评估)两个绑定.
创建函数(评估function1 = function() { ... }
)后,内存如下所示:
+------------------------------------------------------------------------+
| |
v |
+-(Global) lexical environment-+ +-Environment Record-+ +-----Function Object-+---+
+-------------+----------------+ +---------+----------+ +---------------+-----+---+
| Environment | *--------+--->|function1| *-----+---->|[[Environment]]| * |
| Record | | +---------+----------+ +---------------+---------+
+-------------+----------------+ |function3|undefined | | name |function1|
| Outer | | +---------+----------+ +---------------+---------+
| lexical | (empty) |
| environment | |
+-------------+----------------+
Run Code Online (Sandbox Code Playgroud)
现在function1
有一个值,一个函数对象.函数对象具有多个内部(例如[[Environment]]
)和外部(例如name
)属性.顾名思义,无法从用户代码访问内部属性.该[[Environment]]
物业非常重要.注意它是如何引用函数创建的词法环境的!
下一步是执行function3 = function1()
,即调用function2
.正如我在一开始所说,每当执行一个函数时,都会创建一个新的词法环境.让我们在进入函数后看一下内存:
+------------------------------------------------------------------------+
| |
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 | | |
| +-------------+--------+-------+
| |
+-------------------------+
Run Code Online (Sandbox Code Playgroud)
这看起来非常类似于全球环境的结构!我们有一个词法环境,其环境记录包含两个未初始化的绑定.但现在最大的不同是"外部词汇环境"指向全球词汇环境.怎么可能?
在调用function1
和创建新的词法环境时,我们将新环境"外部词汇环境"字段的值设置为function1
's [[Environment]]
字段的值.这是范围链创建的.
现在,执行后function1
,内存具有以下结构:
+------------------------------------------------------------------------+
| |
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 | | | +---------------+---------+
| +-------------+--------+-------+
| |
+-------------------------+
Run Code Online (Sandbox Code Playgroud)
类似的function1
,function2
有一个通过调用创建的环境的引用function2
.另外,function3
指的是我们创建的函数,因为我们从中返回它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 | | |
| +-------------+--------+-------+
+------------------------+
Run Code Online (Sandbox Code Playgroud)
类似于此处,创建了一个新环境,其"外部词汇环境"字段指向function1
被调用时创建的环境.
现在,查找值argument
很简单,因为它存在于环境自己的记录中.但是当查找时variable
,会发生以下情况:由于它不存在于环境自己的记录中,因此它会查看其"外部词汇环境"的记录.它可以做到这一点,因为它有一个参考.
归档时间: |
|
查看次数: |
987 次 |
最近记录: |