JavaScript中的函数expression式与声明之间有什么区别?

以下几行代码有什么区别?

//Function declaration function foo() { return 5; } //Anonymous function expression var foo = function() { return 5; } //Named function expression var foo = function foo() { return 5; } 
  • 什么是命名/匿名函数expression式?
  • 什么是声明的function?
  • 浏览器如何处理这些结构的不同?

对类似问题( var functionName = function(){})对函数functionName(){} )的回应是不是完全正确?

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

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

函数expression式仅在解释器到达该行代码时加载。

所以如果你在加载之前试图调用一个函数expression式,你会得到一个错误! 如果你调用一个函数声明,它会一直工作,因为在加载所有的声明之前,不能调用代码。

示例:函数expression式

 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 = function foo() { return 5; } var foo = function foo() { return 5; }和另外两个真的是一样的。 这只是这行代码用于导致safari中的错误,虽然它不再。

函数声明

 function foo() { ... } 

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

函数expression式

  1. 命名的函数expression式

     var foo = function bar() { ... } 
  2. 匿名函数expression式

     var foo = function() { ... } 

foo()只能在创build后调用。

立即调用函数expression式(IIFE)

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

结论

Crockfordbuild议使用函数expression式,因为它清楚地表明foo是一个包含函数值的variables。 那么,我个人更喜欢使用“宣言”,除非有expression的理由。

关于第三个定义:

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

下面是一个演示如何使用recursion调用的可能性的例子:

 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 

第一个声明取决于声明的上下文。

如果在全局上下文中声明,它将创build一个名为“foo”的隐含全局variables,它将是一个指向该函数的variables。 因此,函数调用“foo()”可以在你的JavaScript程序中的任何地方。

如果函数是在闭包中创build的,它将创build一个名为“foo”的隐含局部variables,然后可以使用它调用闭包中的函数“foo()”

编辑:

我也应该说,函数语句(第一个)在函数expression式(其他2)之前被parsing。 这意味着如果您在脚本的底部声明函数,您仍然可以在顶部使用它。 函数expression式只有在执行代码被命中时才会被评估。

结束编辑

陈述2和3几乎相当于对方。 再次,如果在全局上下文中使用,它们将创build全局variables,如果在闭包中使用,将创build局部variables。 但值得注意的是,语句3将忽略函数名,所以本质上你可以调用函数。 因此

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

是相同的

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

虽然完整的区别比较复杂,但是关心我的唯一区别就是机器创build函数对象的时候。 在声明的情况下,在执行任何语句之前,但是在调用一个声明体(是全局代码体或一个子函数的声明)之前,在expression式的情况下是执行声明的时候。 除此之外,所有的意图和目的浏览器对待他们是一样的。

为了帮助你理解,看看这个性能testing ,这个性能testing是在我调用了外部函数的时候,不需要被机器重新创build的内部声明的函数。 有点耻辱,因为我喜欢这样写代码。