js语言的两个核心技术-----------异步和闭包
Question1:那么什么是闭包呢? 通俗的说法就是外层函数包裹内层函数,内层函数可以调用外层函数的变量.............
(这种解释怎么都感觉有种自欺欺人的样子,看来还是需要进一步了解它的前世今生才能说,我理解撒是闭包)
----------------------------------------------------------------
俗话说得好,他山之石可以攻玉,有几本书是如此来介绍闭包的:
NO1:闭包是指有权访问另一个函数作用域中的变量的函数(这个比较通俗易理解)
NO2:函数对象可以通过作用域关联起来,函数体内的变量都可以保存在函数作用域中,这在计算机科学文献中称为'闭包',所有的javascript函数都是闭包
NO3:闭包是基于语法作用域书写代码时所产生的必然结果(说起来有点玄乎)
NO4:函数可以通过作用域链关联起来,函数内部的变量可以保存在其它函数作用域内,这种特性在计算机科学文献中称为闭包
----------------------------------------------------------------
我们从语法作用域到作用域链的概念再到闭包的形成过程来梳理一下'闭包'
语法作用域
要理解语法作用域,我们先来解释JS的编译阶段,it goes without saying that JS is the weakly typed language, 所谓的弱类型是指不用预定义变量的存储类型,不过这个弱类型不能完全概括JS和其它语言的区别,我们这里再来引出-----'编译语言'(comes from<<你不知道的javascript>>)
编译语言
编译语言在执行之前要经历三个阶段,这三个阶段就像过滤器一样,将我们写的代码转换成语言内部特定的可执行代码,比如我们写的代码是var a=1;而JS引擎内部定义的格式是 var,a,=,1 那在编译阶段 就需要把他们进行转换.这只是一个比喻,而事实上这只是在编译阶段的第一个阶段所做的事下面分析三个阶段做了什么.
1.分词/语法分析(Tokenizing/Lexing)
其实我们写的代码就是字符串,在编译的第一个阶段,把这些字符串转换成 语法单元(toekn), 语法单元我们可以想象成我们上面分解的表达式那样.(注意这个不步骤可能有两种可能,当前这属于 分词,而 语法分析, 会在下面和语法作用域一起说.)
2.解析/语法分析(Parsing)
在有了语法单词之后,JS还需要继续分析代码中的语法以便JS引擎减小负担(总不能在引擎运行的过程中让它承受这么多轮的转换规则吧?),通过语法单元生成了一个 抽象语法树,(abstract syntax tree),它的作用是为JS引擎构造出一份程序语法树,我们简称为AST,这时我们不禁联想到DOM 树,他们都是树,以 var,a,=,1为例,它会以层为单元划分他们,例如:顶层有一个stepA里面包含着'v',stepA下面有一个stepB,stepB中包含有'a',就这样一层一层嵌套下去...
3.代码生成(raw code)
这个阶段主要做的就是拿AST来生成一份JS语言内部认可的 代码(这时语言内部制定的,并不是二进制),在生成的过程中,编译器还会询问作用域的问题,还是以var a=1为例,编译器首先会询问作用域,当前有没有变量a,如果有则忽略,否则在当前作用域下创建一个叫做a的变量
语法阶段
上面概括的只是所有编译语言最基本的流程,对于我们的JS而言,它在编译阶段做的事情不仅仅是那些,它会提前为js引擎做一些性能优化等工作,总之,编译器干的事情超乎你的想象.
语法作用域是发生在编译阶段的第一个步骤当中,也就是分词/词法分析阶段.它有两种可能,分词和语法分析,分词是无状态的,而语法分析是有状态的.
---------------未完待续.....