此文讨论一下函数声明和函数表达式的一些不同之处,以及最蛋疼的优先问题,是初级文章。
之所以写本文是因为在网上看到一篇与此相关的文章,里面给出了结果但没有分析原因,而我自己也对此有些不肯定,所以我决定自己尝试一下,并记录下来,以便以后再也不用思考这类问题。
函数声明即function name () {}这样的代码。首先,我们要确定以下代码是完全正确的:
t1(); function t1(){ console.log("t1"); }
即函数可以提前调用然后再声明。
为什么可以这样?是因为javascript代码是一段一段预载的(即一组script标签),在一段代码预载完成后,会把函数声明提前到代码段的前面执行,以便在代码段的任何地方调用,所以前面的代码无错——不知道真实原理是不是如此,类似吧。
而函数表达式,就是把一个匿名函数附给一个变量,以后想要调用这个函数时,就直接调用这个变量即可。如:
var t1 = function(){ console.log("new new t1"); } t1();
函数表达式就没有直接函数声明的优点,即他不能先调用再来声明。
为什么呢?因为函数表达式是把函数附给一个变量做为他的值,而变量在没有声明之前就调用是要出错的——这个原理好懂吧?
其实我把原理一讲,好像下面的题目就变得毫无难度了,不过我还是写出来给大家讲一下吧。题目1:
function t1(){ console.log("t1"); } t1(); function t1(){ console.log("new t1"); } t1(); var t1 = function(){ console.log("new new t1"); } t1(); var t1 = function (){ console.log("new new new t1"); } t1();
请判断以上代码的输出结果。当然,肯定不会是以下结果:
t1,
new t1,
new new t1,
new new new t1
这就涉及到前面讲的“函数声明会提前”的问题,上面的代码其实和下面的代码是一样的:
function t1(){ console.log("t1"); } function t1(){ console.log("new t1"); } t1(); t1(); var t1 = function(){ console.log("new new t1"); } t1(); var t1 = function (){ console.log("new new new t1"); } t1();
这样一排相信大部分人一下就说出正确结果了,就是:
new t1
new t1
new new t1
new new new t1
因为上面的代码有两个同名函数声明,而很明显后面的同名函数会覆盖之前的函数,所以只有”new t1″是生效的——这一点,没有疑问吧?
而后面的两个var t1,则不存在提前的问题,但他们依然会覆盖同名元素,导致之前的同名元素(即t1函数声明)被替换了。
下面把题目改一下,变成题目2:
function t1(){ console.log("t1"); } t1(); function t1(){ console.log("new t1"); } t1(); var t1 = function(){ console.log("new new t1"); } t1(); //注意下面这最后一个 function t1(){ console.log("new new new t1"); } t1();
这段代码要注意的是最后一个地方,即把之前的var t1的函数表达式改成了function t1()这种函数声明。这道题目结果如何呢?
还是用前面的“提前原则”整理一下代码,整理后如下:
function t1(){ console.log("t1"); } function t1(){ console.log("new t1"); } function t1(){ console.log("new new new t1"); } t1(); t1(); var t1 = function(){ console.log("new new t1"); } t1(); t1();
整理之后又发现,代码变得毫无难度了:前面3个同名函数声明,同样只有最后一个生效,所以紧随其后的两次t1()调用都输出new new new t1,而后面的var t1又覆盖了之前的函数声明,所以其后的两次t1()调用会输出覆盖后的结果,即new new t1。
new new new t1
new new new t1
new new t1
new new t1
题目2与题目1的代码就差别在最后一个函数的声明方式,但输出结果却面目全非。
写成之后发现我写了一篇如此简单的文章,呃。总之你记住,直接函数声明会提前,函数表达式则不会,就行了。整理代码顺序的时候不要出错。