javascript编译与运行的几个实验
在开始写博文之前,我必须要提一句:我是一个很菜很菜的菜鸟。不过我一直在通过自己的学习与积累,让自己变得强大。由于我的语言组织能力水平不堪一击,于是,如果你是一位希望看到优美文字的coder,我只希望你勿喷。而我的见解也是很有限的,希望大神们看了多多提意见,让我这位在迷途中的菜鸟有个改变的方向。好了,接下来进入主题。
最近我在看朱印宏老师主编的《javascript 征途》这一本巨作,由于是巨作,而我这种菜鸟自然看起来会很吃力了。所以我咬着牙,不算完整的看了一遍。但我晚上缓过神来打算照着书上的实例来研究一下闭包这个让我各种忧伤,各种糊里糊涂的章节时。我突然发现对于var的作用域我已经迷途了。于是我找了下度娘,看她是否你知道迷津。于是我找到园中的洞庭啸月 的这一篇javascript中的var浅析一文,经过上上下下看了几遍,我终于有了一些拨开云雾了。一下为我自己的一些实验,其中包含着我对闭包现在的理解,以及javascript解析机制的理解。
先来个最简单的:
1 f5(); //调用f5(),f5函数定于在window这个全局作用域之中。结果:5 2 alert(b); //结果:undefined 3 var b = 0; //定于全局变量 b=0 4 alert(b); //结果:1 5 function f5() { 6 7 b = 5; //起到覆盖的作用 8 9 alert(b); 10 11 }
通过上面的实验我们可以看出在函数和变量在javascript是经历过预编译期和执行期两个过程的。以下为朱印宏老师主编的《javascript 征途》书中的原话:“在预编译期,使用var语句声明的变量和使用function语句声明的函数都会被处理。但是,javascript 解释器只是对var语句声明的变量进行索引,变量的初始化值却被忽略,直到执行期时才去为变量读取初始值。而对于function语句创建的函数,javascript解释器不仅对函数名称按变量标识进行索引,而且对函数提前进行了处理。于是在预编译期,同名的变量被后来的变量所覆盖。”
上面这些只要懂一点点javascript的人应该就能懂了。
接下来我上一段让人迷糊的代码;
javascript代码:
1 var b = 0; 2 function f1() { 3 alert(b); 4 var b = 1; 5 f2 = function () { 6 var b = 2; 7 alert(b); 8 f6 = function () { 9 alert(b); 10 } 11 } 12 f3 = function () { 13 alert(b); 14 b = 3; 15 16 } 17 f4= function () { 18 alert(b); 19 } 20 }
HTML代码:
<div> <button onclick="f1()">f1()</button> <button onclick="f2()">f2()</button> <button onclick="f3()">f3()</button> <button onclick="f4()">f4()</button> <button onclick="f6()">f6()</button> </div>
有趣的是在按钮中点顺序如果发生变化会出现多种不同的结果:
第一种:1,2,3,4,6这对应的结果为:undefined,2,1,3,2
第二种:不点击1,直接点击2,3,4,6。则没有什么反应,通过调用firebug我们可以看到都是出现了如下错误提示:
ReferenceError: f6 is not defined
上面的对比我们可以看出:闭包的内部第一层函数执行过程。首先函数f1()预编译,当执行过一遍f1()之后,f1()这个函数的内部函数执行时才会被触发,这如同,你要得到蛋黄你一定要先把蛋壳给打破了才能一样。(ps:这边存在一些问题,我对闭包至今还是迷糊的,上面的描述可能存在问题,希望懂的人给点指示。而上面的比喻只是我的愚见。)
第三种:1,不点击2,接着点击,6 。结果为:undefined,报错:
ReferenceError: f6 is not defined
第四种:1,2,6 结果为:undefined,2,2
综合上面三、四两种我们可以看出:如果只是执行了f1()但是不执行f2()这时会出现嵌套在f2()内部的f6()还是不能执行,因此我们。单击f6()会报错。所以javascript的对于嵌套的函数就像剥洋葱一样,想要运行里面的就一定要先运行包裹着它的那一层。因此,如果没有错误的话,javascript对于function的声明只是预编译全局作用域的。(这边包含,闭包的知识,由于我不了解就不用闭包这个词语了。)
第五种:点击1,4 。结果:undefined,1。
第六种:点击1,3,4.。结果为:undefined,1,3。
第七种:单击1,4,3,4,3。结果为:undefined,1,1,3,3。
通过五、六、七这三个比较我们可以得出这样一个结论:其实函数内的变量都是先定义,后赋值的,不管定义变量的语句写在何处。而且要明白,在函数外面定义变量的时候,有没有var都无所谓,在函数内部定义变量,如果前面有var就代表是函数内的局部变量,否则为调用全局变量。(此话来之javascript中的var浅析)