javascript中声明函数常用的方法有两种:函数声明式和函数表达式.
一、定义
下面分别用两种方法定义函数:
//函数声明式 function greeting(){ console.log("hello world"); } //函数表达式 var greeting = function(){ console.log("hello world"); }
二、区别:
1).以函数声明的方法定义的函数,函数名是必须的,而函数表达式的函数名是可选的。
如果函数表达式声明的函数有函数名,那么这个函数名就相当于这个函数的一个局部变量,只能在函数内部调用,举个栗子:
var f = function fact(x) { if (x <= 1) return 1; else return x*fact(x-1); }; alert(fact()); // Uncaught ReferenceError: fact is not defined
2).以函数声明的方法定义的函数,函数可以在函数声明之前调用,而函数表达式的函数只能在声明之后调用(函数声明整体会被提升到当前作用域的顶部,函数表达式也提升到顶部但是只有其变量名提升,变量提升详解:https://www.cnblogs.com/vickylinj/p/12190847.html) :
函数表达式与其他表达式一样,在使用前必须先赋值。以下代码会导致错误。
sayHi(); //错误:函数还不存在 var sayHi = function(){ alert("Hi!"); };
3).以函数声明的方法定义的函数并不是真正的声明,它们仅仅可以出现在全局中,或者嵌套在其他的函数中,但是它们不能出现在循环,条件或者try/catch/finally中,而函数表达式可以在任何地方声明。换句话说,函数声明不是一个完整的语句,所以不能出现在if-else,for循环,finally,try catch语句以及with语句中。
为什么if else 语句里不能用函数声明定义函数,而可以用函数表达式定义函数:
//不要这样做! if(condition){ function sayHi(){ alert("Hi!"); } } else { function sayHi(){ alert("Yo!"); } }
表面上看,以上代码表示在 condition 为 true 时,使用一个 sayHi()的定义;否则,就使用另一个定义。实际上,这在 ECMAScript 中属于无效语法, JavaScript 引擎会尝试修正错误,将其转换为合理的状态。但问题是浏览器尝试修正错误的做法并不一致。大多数浏览器会返回第二个声明,忽略condition; Firefox 会在 condition 为 true 时返回第一个声明。因此这种使用方式很危险,不应该
出现在你的代码中。不过,如果是使用函数表达式,那就没有什么问题了。
为什么属于无效的语法呢?这要从词法作用来说,在《JavaScript语言精髓与编程实践》第3章3.2基本语法的结构化含义 ,其中3.2.2.2语法作用域的相关性这一小节回答了以上的疑问,以下属于摘抄部分:
上面的代码function的语法作用比表达式的语法作用域高,所以上面if。。。else。。。语句不能包含函数的词法作用域,JavaScript会将其理解为“平行”的关系,即如下所示:
本例中的代码也会理解为:
if(condition){} else {} function sayHi(){ alert("Hi!"); } function sayHi(){ alert("Yo!"); )
相当于第二个sayHi()函数覆盖了第一个,所以会大多数浏览器会返回第二个声明,忽略condition。
当然书中也建议如下作:
//可以这样做 var sayHi; if(condition){ sayHi = function(){ alert("Hi!"); }; } else { sayHi = function(){ alert("Yo!"); }; }
这个例子不会有什么意外,不同的函数会根据 condition 被赋值给 sayHi。
参照1:https://www.cnblogs.com/menghome/p/9277855.html
参照2:https://blog.csdn.net/qq_41846861/article/details/92692268