这个问题在这里已有答案:
以下代码行之间有什么区别?
//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() {})的回答怎么回事?
5 回答
它们实际上非常相似 . 你如何称呼它们完全相同 . 不同之处在于浏览器如何将它们加载到执行上下文中 .
函数声明在执行任何代码之前加载 .
函数表达式仅在解释器到达该行代码时加载 .
因此,如果您尝试在加载之前调用函数表达式,则会出现错误!如果你调用一个函数声明,它将始终有效,因为在加载所有声明之前不能调用任何代码 .
Example: Function Expression
Example: Function Declaration
至于你问题的第二部分:
var foo = function foo() { return 5; }
与其他两个真的相同 . 只是这行代码用于导致safari中的错误,尽管它不再存在 .功能声明
由于 function hoisting ,可以在定义之前和之前调用以这种方式声明的函数 .
函数表达式
foo()
只能在创建后调用 .立即调用函数表达式(IIFE)
结论
Crockford建议使用函数表达式,因为它清楚地表明
foo
是一个包含函数值的变量 . 嗯,就个人而言,我更喜欢使用声明,除非有表达的理由 .关于第3个定义:
下面是一个示例,说明如何使用递归调用的可能性:
编辑:更有趣的闭包示例:
第一个语句取决于声明它的上下文 .
如果它在全局上下文中声明,它将创建一个名为“foo”的隐含全局变量,它将是一个指向函数的变量 . 因此,函数调用“foo()”可以在你的javascript程序中的任何地方进行 .
如果函数是在闭包中创建的,它将创建一个名为“foo”的隐含局部变量,然后您可以使用“foo()”来调用闭包内的函数 .
EDIT:
我还应该说函数语句(第一个)在函数表达式之前被解析(另外2个) . 这意味着如果您在脚本底部声明了该功能,您仍然可以在顶部使用它 . 函数表达式仅在执行代码命中时才会得到评估 .
END EDIT
陈述2和3几乎相同 . 同样,如果在全局上下文中使用它们将创建全局变量,并且如果在闭包内使用它将创建局部变量 . 但值得注意的是语句3将忽略函数名称,所以你可以调用函数 . 因此
是相同的
虽然完全不同之处更复杂,但我唯一的不同之处在于机器创建功能对象时 . 在声明的情况下,在执行任何语句之前但是在调用语句体之后(是全局代码体或子函数),并且在表达式的情况下是在它执行的语句被执行时 . 除了所有意图和目的之外,浏览器对它们的处理方式相同 .
为了帮助您理解,请查看这个性能test,它破坏了我在调用外部函数时不需要由机器重新创建的内部声明函数的假设 . 有点羞耻,因为我喜欢用这种方式编写代码 .