首先为什么我的第一篇文章会是JS的而不是其他分类的文章呢!很简单,因为今天在整理笔记的时候第一篇看到的就是关于JS的,而且还是关于函数的,对于JS中的函数,那是真的活到几岁说到几岁,因为它真的是JS中的大牌人物,在《javascript征途》这本书中提到过,一切JS源于函数,很奇怪对于这样一种几乎面向对象的语言,不是应该一切源于对象吗,怎么会是函数呢?而且在这本书中,函数是object类型的,在其他的一些关于JS的书中,有些直接将函数写为function类型算了,其实这也不为过,函数在JS里面的复杂程度绝对不亚于对象,下面,我们将通过一系列关于函数的小文章,来慢慢了解这个令人头疼的家伙。

    一开始,我们要了解一下JS这门语言的运行机制,它不像其他一些OO语言如C++是编译性的语言,而是解释性的语言,也就是说,JS将我们的代码一句一句地翻译出来,而不是整篇代码,这就好比我们将英文翻译成中文一样,你可以出一本书,将整篇文章翻译过来,以后要用直接翻书看,这是编译性;你也可以一句一句口头翻译给别人听,这样子快,但是当下一次别人还行听的时候你就得再翻译一次,这是解释性。

    JS的运行机制是预编译->解释执行,请注意预编译不是编译,它是将所有JS代码里面的一些东西先做一些准备,好让待会解释的时候容易点,就好像口头翻译时你要先看一下那篇文章心里默读一遍才行。函数,恰恰好就是在预编译阶段就被赋值并初始化的,而像变量还有匿名函数,则要到解释执行阶段才会赋值。再打个比方,小明和小雄都收到通知说星期五的时候要交作业,然后小明在星期三的时候就已经把作业做好,而小雄则说要等到星期五那天上课才去课堂写作业并交作业。这时候小明的作业相当于预编译的函数,是先执行完了,星期五的时候小明可以不去上课直接叫人交作业,但小雄不行,他在星期五要自己去课堂写作业并交作业,小雄的作业就是变量或者匿名函数。

    现在看以下代码:

 

<script type="text/javascript">
function f() {
            return 1;
        }
        alert(f());
        function f() {
            return 2;
        }
        alert(f());
</script>

    大家猜猜结果会是什么,恩,结果不是我们想的1,2而是两个对话框都显示2.

 

    原因在于JS在对这段代码进行预编译的时候,先初始化了第一个f()函数,然后再处理第二个同名函数f(),由于同名,所以第二个函数将第一个函数覆盖了,而两句alert语句是要等到运行的时候才会被处理,所以其实上面这段代码可以将其看成是:

 

<script type="text/javascript">
        function f() {
            return 2;
        }
        alert(f());
       
        alert(f());
    </script>

    原因就是第二个f()将第一个f()覆盖了;

 

    再看以下代码:

 

<script type="text/javascript">
        var f=function(){
            return 1;
        }
        alert(f());
        function f() {
            return 2;
        }
        alert(f());
    </script>

   再次运行,出现两次1,这次将第一个f变量改为匿名函数,同样的匿名函数在预编译阶段也不会被赋值,而下面那个f()是函数对象,在预编译时被初始化,所以此段代码在运行时就变成如下代码:

 

 

<script type="text/javascript">
        function f() {
            return 2;
        }        

        var f=function(){
            return 1;
        }
        alert(f());
       
        alert(f());
    </script>

   先是在预编译时候定义f()函数返回2,但是运行时首先遇到f()这个同名匿名函数,这样它就将原来那个函数覆盖掉,以至于下面执行两次alert都出现1;

 

   但是我其实一开始就想让它出现1,2的,这样子做不是背道而驰了嘛,不急,接下来继续,请看下面一段代码

 

<script type="text/javascript">
        function f(){
            return 1;
        }
        alert(f());
       var f=function(){
            return 2;
        }
        alert(f());
    </script>

    这个时候终于出现1,2了,我们要的结果(应该说是我要的结果),一样的道理,在预编译阶段,第一个f()被初始化,第二个f由于是匿名函数,所以在运行时才被真正执行,所以,代码从上到下顺序执行,先是alert第一次出现1,然后第二个同名匿名函数这时候被初始化,覆盖掉原来的f(),所以第二次alert的时候就出现2了,大功告成。

 

    通过以上几个简单的例子,我们可以大致了解到函数在JS的运行机制中是处于一个怎么样的地位,同时,我们也该清楚,匿名函数不会像对象函数那样,在预编译阶段就被赋值。了解预编译是什么,函数如何在预编译里面先被执行,这对于我们以后学JS的函数的时候有着莫大的帮助。

    需要注意的是,以上例子中的同名函数f都是放在同一个<script></script>代码段中,所以函数会发生覆盖,如果两个同名函数位于两个分开的代码段中,是不会出现覆盖的。好了,今天就写到这里,打字打得好辛苦,函数还有说不完的事,以后我们会接着学习,看看是函数玩死我们还是我们玩死函数~~~~~