定义函数有两种方法:一种是函数声明,另一种是函数表达式。

1. 函数声明

  1. function functionName(arg0, arg1, arg2) {
  2. //函数体
  3. }

FireFox、Safari、Chrome 和 Opera 都给函数定义了一个非标准的 name 属性,通过这个属性可以访问到给函数指定的名字,也就是 function 关键字后面的标识符。

  1. //只在 FireFox、Safari、Chrome 和 Opera 有效
  2. alert(functionName.name);

关于函数声明,一个重要的特征就是函数声明提升,意思是在执行代码之前会先读取函数声明,这意味着可以把函数声明放在调用它的语句后面。

  1. sayHi(); //正确,因为函数声明提升
  2. function sayHi() {
  3. alert("Hi!");
  4. }

2. 函数表达式

  1. var functionName = function(arg0, arg1, arg2) {
  2. //函数体
  3. }

这种语句就像是变量赋值语句,即创建一个函数并将它赋值给变量。这种函数叫做匿名函数,因为 function 关键字后面没有标识符,匿名函数的 name 属性是空字符串。

函数表达式与其他表达式一样,在使用前必须先赋值。

  1. sayHi(); //抛出错误,因为函数还不存在
  2. var sayHi = function() {
  3. alert("Hi!");
  4. }

使用函数表达式,相当于函数名是左边表达式,而不再会是右边的表达式中的名称。如果右边使用具名函数,那么不管是前面后面使用这个具名函数,都会报错。

  1. let a = function b() {
  2. }
  3. b; //=> undefined
  4. a; //=> function

3. 区别

理解函数提升的关键,就是理解函数声明和函数表达式之间的区别。

  1. //错误,不能这样做
  2. if(condition) {
  3. function sayHi() {
  4. alert("Hi!");
  5. }
  6. }
  7. else {
  8. function sayHi() {
  9. alert("YO!");
  10. }
  11. }
  12. //正确,可以使用函数表达式
  13. var sayHi;
  14. if(condition) {
  15. sayHi = function() {
  16. alert("Hi!");
  17. }
  18. }
  19. else {
  20. sayHi = function() {
  21. alert("YO!");
  22. }
  23. }

能够创建函数再赋值给变量,也就能够把函数作为其他函数的值返回

  1. function createComparisonFunction(propertyName) {
  2. return function(object1, object2) {
  3. var value1 = object1[propertyName];
  4. var value2 = object2[propertyName];
  5. if (value1 < value2) {
  6. return -1;
  7. }
  8. else if (value1 > value2) {
  9. return 1;
  10. }
  11. else {
  12. return 0;
  13. }
  14. }
  15. }

这样就返回了一个匿名函数,返回的函数可能被赋值给一个变量,或者以其他方式被调用