1 函数创建方法
1.1 函数声明
使用函数声明方法创建函数时,显示function关键字,然后是函数名、参数列表和函数体,如:
function fnName(arg1, arg2) {
函数体逻辑......
}
1.2 函数表达式
首先介绍以下匿名函数。使用函数声明创建的函数可称为具名函数,那么匿名函数顾名思义,就是函数名隐匿起来的函数。匿名函数与具名函数就函数外形而言,只是函数名的有无上的区别。
// 匿名函数
function(arg1, arg2) {
// 函数体
}
使用函数表达式方式创建函数,是将一个匿名函数赋值给一个变量,就像一个表达式一样。
// 函数表达式
let fnName = function(arg1, arg2) {
// 函数体
}
2 函数声明提升
函数声明与函数表达式的一个区别是:函数声明可以先调用后声明,函数表达式必须先声明后调用。
// 先调用后声明,两种函数结果比较
// 函数声明
sayHello(); // hello
function sayHello() { console.log('hello') }
// 函数表达式
sayHi(); // Uncaught ReferenceError: say is not defined
let sayHi = function() { console.log('Hi') }
// 先声明后调用,两种函数比较
// 函数声明
function sayHello() { console.log('hello') }
sayHello(); // hello
// 函数表达式
let sayHi = function() { console.log('Hi') }
sayHi(); // Hi
由以上两个例子可以看出,函数声明可以先声明后调用,也可以先调用后声明;函数表达式要先声明后调用,不可以先调用后声明。
之所以会有这样一个区别,是因为函数声明存在函数声明提升,也就是JavaScript在执行代码之前会先读取函数声明。因此,即使代码中是先使用函数,再进行函数声明,但在代码执行前已经读取了函数声明,知道了函数的存在,所以实行函数时不会发生错误。函数表达式不存在函数声明提升,所以先使用后定义时,不知道函数的存在,就会报错。
由于存在函数声明提升,因此不应该将函数声明在不确定的分支代码中,否则会发生意向不到的情况。
if(condition) {
function fnName() { console.log('hello') }
} else {
function fnName() { console.log('goodbye') }
}
在这段代码中,你想得到的结果是:当condition为true时,函数结果时hello;当condition为false时,函数结果是hi。
但是这段代码确不能如你所愿,在不同的浏览器中的到的是不同的结果,因为这在ECMAScript中属于无效的语法。
如果你想实现上面说到的效果,你可以这样做:
let fnName;
if(condition) {
fnName = function() { console.log('hello') }
} else {
fnName = function() { console.log('goodbye') }
}
3 总结
函数声明提升造成了函数声明与函数表达式所创建的函数在使用上的差异:函数声明可以先声明后调用,也可以先调用后声明;函数表达式要先声明后调用,不可以先调用后声明。这个差异也使得函数声明不能声明在不确定能否执行的分支代码中,如果想要在分支代码中声明函数,可使用函数表达式。