2009-06-18 158 views
410

以下几行代码有什么区别?JavaScript中的函数表达式与声明有什么区别?

//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() {})的回答不完全正确吗?

+0

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

继承人它展示了如何使用递归调用的可能性的例子这是[关于命名函数表达式的好文章](http://kangax.github.com/nfe)。函数表达式与声明在第一节中讨论。 – 2009-06-18 17:09:25

+0

海事组织的主要区别在于提升。这里是关于这个主题的一篇很好的文章:http://www.adequatelygood.com/JavaScript-Scoping-and-Histing.html – 2014-11-18 18:03:59

回答

10

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

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

如果在一个封闭创建功能,将创建一个名为“富”然后你就可以用它来调用闭包功能与“富()”隐含的局部变量

编辑:

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

END EDIT

语句2 & 3相当于彼此几乎。再次,如果在全局上下文中使用,它们将创建全局变量,并且如果在闭包中使用,则会创建局部变量。但值得注意的是,语句3将忽略函数名称,所以本质上你可以调用函数。因此

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

相同

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

`fooYou`不被忽略。它在函数体中可见,所以函数可以引用它自己(例如实现递归)。 – 2010-07-27 14:06:36

+1

这是一个很好的观点。我没有想到:) – Alex 2011-04-30 08:59:22

+7

另外,命名函数表达式对调试很有用:`var foo = function fooYou(){return 5; };的console.log(FOO); console.log(foo.name);`将打印fooYou()/ fooYou`(Firefox),`[Function:fooYou]/fooYou`(node.js),`function fooYou(){return 5; }/fooYou`(Chrome)或这些行的独立内容,具体取决于您执行的位置。 – Gilead 2013-01-15 15:41:57

335

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

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

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

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

举例:函数表达式

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; }是真正的SAM另外两个。这只是这行代码用于导致safari中的错误,尽管它不再。

1

虽然完整的区别比较复杂,但唯一与我有关的区别是机器创建函数对象时。在声明的情况下,在执行任何语句之前,但是在调用声明体(是全局代码体或子函数的声明)之前,对于表达式而言,它是在执行声明时执行。除此之外,所有的意图和目的都是浏览器对待它们。

为了帮助你理解,看看这个性能test,它破坏了我内部声明的函数的假设,当外部函数被调用时不需要由机器重新创建。有点耻辱,因为我喜欢这样写代码。

79

函数声明

function foo() { ... } 

因为功能提升的,函数声明这样既可以和之后的定义之前被调用。

函数表达式

  1. 命名的函数表达式

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

    var foo = function() { ... } 
    

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

Immediately-Invoked Function Expression (IIFE)
(function() { ... }()); 

结论

克罗克福德推荐使用函数表达式,因为它清楚地表明,foo是包含函数值的变量。那么,我个人更喜欢使用宣言,除非有表达的理由。

17

关于第三个定义:

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 
相关问题