定义函数的方式
两种方式:
1. 函数表达式
let 变量名 = function [函数名]([形参列表]) {
//函数体
}
- 函数声明语句
function 函数名([形参列表]) {
//函数体
}
注:”[]”里的内容代表可选
区别一:函数表达式可以是匿名函数,函数声明必须要有函数名
例1:
//函数表达式--匿名函数
let factorial = function (x) {
if (x <= 1) return 1;
else return x * factorial(x-1);
}
factorial(5);
//函数表达式--具名函数
let factorial = function fact(x) {
if (x <= 1) return 1;
else return x * fact(x-1);
}
factorial(5);
//函数声明
function factorial(x) {
if (x <= 1) return 1;
else return x * factorial(x-1);
}
factorial(5);
对于有函数名的函数表达式,函数名的作用域只在函数内部,而变量名的作用域是全局的,所以在函数内部即可以使用函数名也可以使用变量名调用自身,在函数外部则只能使用变量名调用:
//函数表达式--具名函数
let factorial = function fact(x) {
if (x <= 1) return 1;
else return x * fact(x-1);//正确
//else return x * factorial(x-1);//正确
}
factorial(5); //正确
fact(5); //错误
区别二:函数表达式不会被提升到作用域顶部,而函数声明会提升。
函数表达式不会被提升到作用域顶部的原因是函数表达式是将函数赋值给一个变量,而js对提升变量的操作是只提升变量的声明而不会提升变量的赋值,所以不能在某个函数表达式之前调用它,但可以在某个函数声明之前调用它。
区别三:函数表达式可以出现在任何地方,函数声明不能出现在循环、条件判断、try/catch、with语句中。
注:这一点貌似有争议,犀牛书的作者持该观点,而有的人却认为函数表达式同样不能出现在块语句中(if, for, while等),但我个人觉得函数表达式是可以出现在任何地方的,因为它的本质其实就是在定义一个变量,只是这个变量的值是函数而已。
注意点一:立即执行函数只能是函数表达式而不能是函数声明,但使用函数声明不会报错,只是不会执行
例2:
//函数声明方式
function square(a){
console.log(a * a);
}(5)
//函数表达式方式
let square = function(a){
console.log(a * a);
}(5)
//错误的方式
function(a){
console.log(a * a);
}(5)
上面的代码第一段不会打印出值,第二段能打印出值,出现这种区别的原因是只有函数声明可以提升,函数声明后面的()直接被忽略掉了,所以它不能立即执行。而第三段代码会报错,因为它既没有函数名又没有赋值给变量,js引擎就会将其解析成函数声明。为了避免在某些情况下js解析函数产生歧义,js建议在立即执行函数的函数体外面加一对圆括号:
例3: