前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Scope chain & Closure

Scope chain & Closure

作者头像
lesM10
发布2019-08-26 16:47:37
5200
发布2019-08-26 16:47:37
举报

本文主要对 Arindam Paul - JavaScript VM internals, EventLoop, Async and ScopeChains视频做个总结。虽然英语水平很差,几乎听不懂这位大佬在说什么。但是我会猜啊?。接下来就把我所猜到的内容分享给大家。

Question:What make programming interesting? Answer:主要有以下2点。 1)Programming is more like art than science。Programming 并不像普遍的科学那样:有着固定的步骤,一成不变。不同Programmer在programming时,会因为对事物认知方式的不同而采用不同的编写方式和编写策略(即使面对的是 同样的task)。 2)Programming就像下象棋一样:虽然了解规则并花不了多少时间,但是 如果想下的相对高明点就需要花费极其多的时间去琢磨 每步的细节,用意,以及对整场游戏的后续影响。从这点上来看:programming更像是艺术一样,需要雕琢。 嗯,好有道理的样子?,上次骗我去柬埔寨讨老婆,现在又想骗我给你打一辈子工,哼?。


代码语言:javascript
复制
    Agenda:
        1)JavaScript Interpretation and Memory Model
        2)  Compilation and Variable Hoisting
        3)  Function Execution
        4)  Scope Chains and Closure
        5)  Javascript Runtime and Event Loop
        6)  Async Example
        7)  Single threaded parallel execution

对于以上这些内容,仅猜到了2,4两点(虽然听不懂大佬讲些什么,但就是觉得讲得牛掰?)。接下来正式展开 所猜到的内容。

Compilation and Variable Hoisting Function Execution 这意味着: 编译时 对所有代码进行逐行检测 。检测到所有的var(var当然也包括函数的定义,但是不包括赋值表达式右侧的函数定义),并分配存储空间。 执行时 遇到未var声明的变量时 沿着scope chain向上查找该变量的定义。如果在scope chain上找到该变量,不再分配存储空间。如果找到global scope时 仍然没有该变量 就在global scope为该变量分配存储空间。 注意是先编译后执行,编译时为所有的变量的定义 分配好存储空间(函数的定义也视作var声明),要区分compilation phase和execution phase。并且编译也不是一次性完成的,每当遇到要执行的函数时,会对要执行的函数进行编译。因此编译和执行时交叉进行的。

下面来看具体的例子,代码如图1所示。

1.png

编译顺序1,2,3,4,18,19,20。Compilation of the main block done(此时不会进入函数f内进行编译)。只有var a,f分配了存储空间。如图2。

2.png

执行顺序1,2,3,4,18,19,20。执行到line 2时,沿scope chain查找,未找到b的var声明,就在global scope中为b分配存储空间。接着执行f(1),为函数f创建local heap memory。 执行f(1)时,再compile函数f(函数f的形参变量z 视作是var声明了的。同样地,在compile函数f时,不会进入函数g内进行编译)。需要注意的是:line17在函数f的编译阶段被分配存储空间(这也就是variable hoisting)。结果如3。

3.png

执行函数f阶段,line5 line6在当前函数f的scope中找不到变量b,c,会沿scope chain向上查找。在global scope找到了变量b。在global scope 没找到变量c(于是在global scope创建变量c)。在函数f的执行阶段 执行到line8时,会在当前函数f的scope中找到var e(并给var e赋值)。执行到line16时,会compile函数g,为函数g分配heap memory。结果如图4。

4.png

类似地,在函数g的编译阶段结束后,结果如图5。 Note:变量的查找是沿scope chain查找的。这也是图5中 绿字的原因。

5.png

执行完line20后,结果如图6。

6.png

接下来看个类似但更深入的例子,如图7。

7.png

跳过不重要的步骤,只关心我们感兴趣的地方。执行完line21后,结果如图8。

8.png

去掉garbage collected的,如图9。

9.png

函数f的scope没有被garbage collected的原因是:myG指向Lamda “g”,并可能通过myG调用g。而执行g时,是需要scope chain作为环境的。所以在scope chain上的函数f的scope是不该也不能被garbage collected。(Scope chain is nothing but Copy of [[scope]] from the definition to the invocation。如图10)到现在为止,闭包closure大概就不难懂了。

10.png

Closure的表现形式如图11。

11.png

什么是closure?如图12。

12.png

需要注意的是:Closure is used and copied as the "outer environment reference" when the funtion is run.(每当函数被调用执行时,函数所在的scope chain就会再次被复制。这么翻译可能不太恰当。)

implicit closure, explicit closure示例 如图13,14。

13.png

14.png

原创作品,转载请注明出处

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.09.11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档