下面几行代码之间的区别是什么?

//Function declaration
function foo() { return 5; }

//Anonymous function expression
var foo = function() { return 5; }

//Named function expression
var foo = function foo() { return 5; }

什么是命名/匿名函数表达式? 什么是声明函数? 浏览器如何以不同的方式处理这些结构?

对类似问题(var functionName = function() {} vs function functionName(){})的响应不完全正确?


第一条语句取决于声明它的上下文。

如果在全局上下文中声明,它将创建一个隐含的全局变量“foo”,它将是一个指向函数的变量。因此,函数调用“foo()”可以在javascript程序的任何地方执行。

如果函数是在闭包中创建的它会创建一个隐含的局部变量foo然后你可以用foo()来调用闭包中的函数

编辑:

我还应该说,函数语句(第一个)在函数表达式(其他两个)之前被解析。这意味着如果你在脚本底部声明了函数,你仍然可以在脚本顶部使用它。函数表达式只有在被执行代码命中时才会被求值。

最后编辑

表述2和表述3彼此相当。同样,如果在全局上下文中使用,它们将创建全局变量,如果在闭包中使用,将创建局部变量。但是值得注意的是,语句3将忽略函数名,所以本质上你可以调用任何函数。因此

var foo = function foo() { return 5; }

var foo = function fooYou() { return 5; }

它们其实很相似。你怎么称呼他们都一样。区别在于浏览器如何将它们加载到执行上下文中。

函数声明在执行任何代码之前加载。

函数表达式只在解释器到达那行代码时加载。

因此,如果你试图在函数表达式加载之前调用它,你会得到一个错误!如果相反地调用函数声明,它将始终工作,因为在加载所有声明之前不能调用任何代码。

示例:函数表达式

alert(foo()); // ERROR! foo wasn't loaded yet
var foo = function() { return 5; } 

示例:函数声明

alert(foo()); // Alerts 5. Declarations are loaded before any code can run.
function foo() { return 5; } 

关于你问题的第二部分:

Var foo =函数foo(){返回5;}和其他两个是一样的。只是这行代码曾经在safari中导致错误,尽管现在已经不再这样了。


虽然完全的区别更加复杂,但我唯一关心的区别是机器创建函数对象的时间。在声明的情况下是在任何语句执行之前,但在调用语句体(无论是全局代码体还是子函数的)之后,在表达式的情况下是在执行它所在的语句时。除此之外,浏览器对它们是一视同仁的。

为了帮助您理解,看一下这个性能测试,它打破了我的一个假设,即内部声明的函数在调用外部函数时不需要由机器重新创建。有点遗憾,因为我喜欢那样写代码。


函数声明

function foo() { ... }

由于函数提升,以这种方式声明的函数可以在定义之后和之前调用。

函数表达式

命名函数表达式 Var foo =函数栏(){…} 匿名函数表达式 Var foo =函数(){…}

Foo()只能在创建后调用。

立即调用函数表达式(IIFE)

(function() { ... }());

结论

Douglas Crockford在他的«JavaScript: The Good Parts»一书中建议使用函数表达式,因为它清楚地表明foo是一个包含函数值的变量。

嗯,就我个人而言,我更喜欢使用声明,除非有理由使用表达式。


关于第三个定义:

var foo = function foo() { return 5; }

这里有一个例子,展示了如何使用递归调用的可能性:

a = function b(i) { 
  if (i>10) {
    return i;
  }
  else {
    return b(++i);
  }
}

console.log(a(5));  // outputs 11
console.log(a(10)); // outputs 11
console.log(a(11)); // outputs 11
console.log(a(15)); // outputs 15

编辑: 更有趣的闭包示例:

a = function(c) {
 return function b(i){
  if (i>c) {
   return i;
  }
  return b(++i);
 }
}
d = a(5);
console.log(d(3)); // outputs 6
console.log(d(8)); // outputs 8