javascript闭包真经

javascript闭包真经

ID:30361365

大小:85.24 KB

页数:11页

时间:2018-12-29

javascript闭包真经_第1页
javascript闭包真经_第2页
javascript闭包真经_第3页
javascript闭包真经_第4页
javascript闭包真经_第5页
资源描述:

《javascript闭包真经》由会员上传分享,免费在线阅读,更多相关内容在应用文档-天天文库

1、Javascript闭包真经继前阵子写完对象真经后,这篇文章我尝试尽力的去讲透Js中的闭包。这里要感谢爱民,爱民的书写得很好,我从中获益良多。不过这次我打算换一种思路来写这篇真经,就是采用提问回答的方式,我下面先提出我要回答的问题,如果读者你都很自信的能够回答上,那么就可以考虑干别的事情去了。如果感觉自己有点把握不准就请给我一步步的寻址吧。:)我保证最后你就会豁然开朗,明白闭包的真谛。问题集:什么是函数实例?什么是函数引用?什么是闭包?闭包里有什么玩意?函数实例、函数引用和闭包有什么联系?闭包的产

2、生的情形?闭包中的标识符的优先级是什么样的?闭包带来的可见性问题。什么是函数实例呢?其实在我们平常书写代码的过程中,写的函数就是一段文本,只是对于编译型语言来说会把它编译为确定的二进制代码,并放到确定的内存位置执行,而对于Js这样的解释型语言,就会在程序运行的时候把这段文本翻译为计算机能懂的话。那么这里函数代码的文本其实就是这个函数的类,而Js引擎解释后的内存中的数据就是这个函数的实例了。所以函数的实例就是Js引擎读过这段代码后在内存中产生的一段数据。什么是函数引用呢?函数引用就是指向刚才所说的那

3、段内存数据的指针。也就是指向某个函数实例的指针。同一份实例可以有多个引用,只要该实例还有指向它的引用,占用的内存就不会被释放。什么是闭包呢?闭包就是函数实例执行过程中动态产生的一块新的内存里的数据集。这句话有可以表达两层意思:最初闭包必须由函数实例被调用(也就是函数实例执行)时才会由Js引擎动态生成;既然闭包也是一段内存区域,当没有依赖于这个内存中数据的引用时,才会被释放,也就是闭包理论上才会被销毁。记住:闭包是执行期的概念!那闭包里有什么玩意呢?这里我要引入Js引擎在语法分析期就构造的两类结构。

4、执行上下文结构(Context)和调用对象结构(CallObject)。我们还是先看一幅图片:从上面的图片我们容易看出,这是描述一个函数实例信息的图。Context结构包含了myFunc函数的类型(FUNCTION)、名称(myFunc)、形式参数(x,y,z)和最关键的CallObject结构的引用(body为CallObject)。而CallObject结构就是很详细的记录了这个函数的全部语法分析结构:内部声明的变量表(localDeclVars)、内部声明的具名函数表(localDeclFu

5、ncs)以及除去以上内容之外的其它所有代码文本的字符串表示(source)。好,现在有了这个语法分析期就产生的CallObject结构,就好分析闭包里面会有什么了。当一个函数实例被调用时,实际上是从这个原型复制了一份CallObject结构到闭包那块空的内存中去。同时会给里面的数据赋值。这里有两个规则,大家要记下:在函数实例开始执行时,localDeclVars中的所有值将被置为undefined;在函数实例执行结束并退出时,localDeclVars不被重置,这就是Js中函数能够在内部保存数据的

6、特性的原因;这个闭包中的CallObject结构中的数据能保留多久取决于是否还有对其的引用存在,所以这里就引出了一个推论,闭包的生存周期不依赖于函数实例。那么对于全局对象呢?是什么样的结构呢?其实和上面的函数实例的基本一样,唯一不同的是,没有Context,因为它在最顶层了。全局对象里面也有一个CallObject,只是这个CallObject有点特殊,就是localDeclVars里面的数据只会初始化一次,且整个CallObject里的数据总不被销毁。除了我讲的复制了一份CallObject,再

7、往里赋值,闭包其实还包括了一个upvalue数组,这里数组里装载的是闭包链上一级闭包中的标识符(localDeclVars和localDeclFuncs及它自身的upvalue数组)的引用函数实例、函数引用和闭包有什么联系呢?要回答这样的问题,就要好好分别理解上面说的这个三个分别指的是什么。然后我想在回答这个问题前,通过代码来感知一些东西。其实有时候人的思维需要一个载体去依靠,也就是我们常说的实践才能出真知。[javascript]functionmyFunc(){this.doFunc=func

8、tion(){}}varobj={};//进入myFunc,取得doFunc()的一个实例myFunc.call(obj);//套取函数实例的一个引用并赋值给funcvarfunc=obj.doFunc;//再次进入myFunc,又取得了doFunc()的一个新实例myFunc.call(obj);//比较两次取得的函数实例,结果显示false,表明是不同的实例print(func===obj.doFunc);//显示false//显示true,表明两个函数实例的代码文本完全一样p

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。