JS 的函数学习...
一切从闭包开始,也从闭包结束...
用权威指南的原话来说就是 如果理解了闭包,就理解了作用域链和函数调用对象,可以真正地宣传自己是一位高级javascript程序员了...
真的可以么....
不废话了 开始吧 我的学习工程是逆向的 就是从不懂到不懂知道懂得了最简单的 于是在向下逐层理解的
写BLOG的话还是 不再现原过程了 从最简单的开始.
变量
在JAVASCRIPT中变量大分的话可可分为两种类型,基本类型和引用类型(MS大多数语言都可以这样分的 - -||)
基本类型:数值(Number),布尔值,null,undefined。
引用类型:对象,数组和函数。
还有字符串呢....(这个以后有机会开专题讨论....)
然后js的垃圾回收的机制是当对象的引用数为0时,则将内存回收。脚本有个共性好像内存共享的都用的叫什么引用计数和写时复制,具体我也不清楚,貌似爱民的书讲过,而且讲的很不错 ,推荐下.
js的代码执行
当js的解释器开始运行时,它首先要做的事情之一就是在执行任何js代码之前,创建一个全局对象。这个对象的属性就是js程序的全局变量。当声明一个js的全局变量时,实际上所做的是定义了那个全局对象的一个属性(选了好多还是橙色好看点)。客户端的就是中这个global object就是windows.而在函数中定义的局部变量,则是作为该函数的调用对象的属性而存储的.
javascript的解释器每次开始执行一个函数时,都会为那个函数创建一个执行环境,每个执行环境都有一个和它关联在一起的作用域链.
js的函数在定义的时候,不但会创建我们可以看到的属性方法,还会创建一个很隐蔽的东西,就是这个作用域链,其实这是个对象列表,这个列表的最顶端就是那个global对象了,最后一个则是该函数所在的外围函数的调用对象,当执行该函数时,首先就会把该函数的调用对象放到这个作用域链尾部。
在上述代码中,我们知道当调用f()的时候,g()会被创建,g()在创建的时候不止保存了变量的z,还保存了一个对象链表 (global obj)-->(f()调用对象),当g()被调用是,这会创建一个g()的调用对象到这个作用域链的尾部,即(global obj)-->(f()的调用对象)-->(g()的调用对象)
接下来再来解释前面有提到的两个概念....(小学语文老师教过这叫倒叙 - - !)
词法作用域:js的函数在定义他们的作用域里运行,而不是在执行他们的作用域里运行。当定义了一个函数,当前的作用域链就保存起来,并且成为函数的内部状态的一部分。
调用对象:js解释器调用一个函数,首先将作用域设置为定义函数的时候起作用的那个作用域链。接下来,他在作用域的前面添加一个新的对象,这就叫做调用对象。(怎么感觉是很欠扁的解释呢....,不管了)
继续。。。
接下来的东西权威指南用了一开始让我觉得根本就是天书的3段文字来描述。。。
我尽自己最大的努力描述的让自己以后在看到下面的文字还能知道所云何物就好...
其实大概就是讲 ,把上述那个例子来说吧:
一、如果f()中没有嵌套函数g()的创建,就不会有什么奇特的事情发生。
二、如果f()创建了g(),而g()只在f()中调用,也不会有什么特别的事情发生。
三、如果不但在f()创建了g(),还让g()在f()之外调用了(有两种方法a:g()作为f()的返回值 b:把g存储为其他对象的属性),那就是见证奇迹发生的时刻了...
这样闭包就来了,g()将带着f()运行时的调用对象被存储到其他地方去了,即f()的一次特定调用的调用对象会依然存在,及时在f()函数本身那次调用已经结束了,却被保存到了g()的作用域链中去了。
javascript函数是将要执行的代码以及执行这些代码的作用域构成的一个综合体,这种代码和作用域的综合体叫做闭包,所有的javascript的函数都是闭包,不过只有当一个嵌套的函数被导出到它所定义的作用域外时,这种闭包才是有趣的.