1、函数声明与函数表达式
函数声明:
function 函数名称 (参数:可选){ 函数体 }
函数表达式(函数语句):
function 函数名称(可选)(参数:可选){ 函数体 }
function foo(){} // 声明,因为它是程序的一部分
var bar = function foo(){}; // 表达式,因为它是赋值表达式的一部分
new function bar(){}; // 表达式,因为它是new表达式
(function(){
function bar(){} // 声明,因为它是函数体的一部分
})();
如果不声明函数名称,则肯定是函数表达式,但如果声明了函数名称,如何判断是函数声明还是函数表达式?
ECMAScript是通过上下文来区分的,如果function 函数名称(){}是作为赋值表达式的一部分的话,那它就是一个函数表达式,如果function 函数名称(){}被包含在一个函数体内,或者位于程序的最顶部的话,那它就是一个函数声明。
函数表达式和函数声明的差别:函数声明在任何表达式解析和求值之前先被解析和求值。如:
alert(fn());
function fn() {
return 'Hello world!';
}
函数声明在条件语句内虽然可以用,但是没有被标准化,也就是说不同的环境可能有不同的执行结果,所以这样情况下,最好使用函数表达式:
// 千万别这样做!
// 因为有的浏览器会返回first的这个function,而有的浏览器返回的却是第二个
if (true) {
function foo() {
return 'first';
}
}
else {
function foo() {
return 'second';
}
}
foo();
// 相反,这样情况,我们要用函数表达式
var foo;
if (true) {
foo = function() {
return 'first';
};
}
else {
foo = function() {
return 'second';
};
}
foo();
小结:函数声明只能出现在程序或函数体内。它不能出现在if、for、while等Block内。Block块内只能含有Statement语句。
同时因为函数表达式不能以function开头,故函数表达式同样不能出现在Statement语句和Block块内。
2、语句函数
在ECMAScript的语法扩展中,有一个是函数语句,目前只有基于Gecko的浏览器实现了该扩展,一般来说不推荐使用
函数语句和函数表达式的区别:
一般语句能用的地方,函数语句也能用,当然也包括Block块中。
函数语句不是在变量初始化期间声明的,而是在运行时声明的——与函数表达式一样。不过,函数语句的标识符一旦声明能在函数的整个作用域生效了。(声明函数——函数,函数表达式——表达式,语句函数——函数)
函数表达式的新名字只能在函数内部作用域内有效,外部作用域无效。
var f = function foo(){
return typeof foo; // foo是在内部作用域内有效
};
// foo在外部用于是不可见的
typeof foo; // "undefined"
f(); // "function"