JavaScript中的函数表达式和声明有什么区别?
以下代码行之间的区别是什么JavaScript中的函数表达式和声明有什么区别?,javascript,Javascript,以下代码行之间的区别是什么 //Function declaration function foo() { return 5; } //Anonymous function expression var foo = function() { return 5; } //Named function expression var foo = function foo() { return 5; } 什么是命名/匿名函数表达式 什么是声明函数 浏览器如何以不同的方式处理这些结构 对类似问题
//Function declaration
function foo() { return 5; }
//Anonymous function expression
var foo = function() { return 5; }
//Named function expression
var foo = function foo() { return 5; }
- 什么是命名/匿名函数表达式李>
- 什么是声明函数李>
- 浏览器如何以不同的方式处理这些结构
对类似问题()的回答有哪些地方不完全正确?第一个语句取决于声明它的上下文 如果在全局上下文中声明,它将创建一个名为“foo”的隐含全局变量,该变量将指向函数。因此,函数调用“foo()”可以在javascript程序中的任何位置进行 如果函数是在闭包中创建的,它将创建一个名为“foo”的隐含局部变量,然后您可以使用该变量在闭包中使用“foo()”调用函数 编辑: 我还应该说函数语句(第一个)是在函数表达式(其他2个)之前解析的。这意味着,如果您在脚本底部声明函数,您仍然可以在顶部使用它。函数表达式只有在被执行代码击中时才被计算 结束编辑 语句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 = function bar() { ... }
var foo = function() { ... }
示例:函数声明
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 bar() { ... }
var foo = function() { ... }
关于你问题的第二部分:
var foo=function foo(){return 5;}
实际上与其他两个相同。只是这一行代码曾经在safari中导致错误,尽管现在已经不是了。虽然完全的区别更复杂,但我唯一关心的区别是机器创建函数对象的时间。在声明的情况下是在执行任何语句之前,但在调用语句体之后(可以是全局代码体或子函数),在表达式的情况下是在执行它所在的语句时。除此之外,无论出于何种目的,浏览器都会对它们一视同仁
为了帮助您理解,看看这个性能,它打破了我对内部声明的函数的假设,在调用外部函数时,不需要机器重新创建这些函数。也有点遗憾,因为我喜欢用这种方式编写代码。函数声明
由于函数提升,以这种方式声明的函数可以在定义之后和之前调用
函数表达式
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 bar() { ... }
var foo = function() { ... }
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 bar() { ... }
var foo = function() { ... }
foo()
只能在创建后调用
结论
Crockford建议使用函数表达式,因为它清楚地表明
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
fooyu
不会被忽略。它在函数体中可见,因此函数可以引用自身(例如,实现递归)。这是一个很好的观点。我没有想到:)另外,命名函数表达式对于调试也很有用:var foo=function fooyu(){return 5;};console.log(foo);console.log(foo.name)
将打印fooYou()/fooYou
(Firefox)、[函数:fooYou]/fooYou
(node.js)、函数fooYou(){return 5;}/fooYou
(Chrome)或单独打印这些行,具体取决于执行它的位置。建议使用命名函数表达式,因为它允许您在内部引用函数,如果你需要的话。例如,递归调用函数或处理其名称或属性。顺便说一下,主要的好处是调试。如果您使用未命名的函数,那么如果发生了什么事情,就很难进行调试,因为您将获得对匿名函数的引用,而不是它的名称。函数表达式和声明在第一节中讨论。IMO的主要区别在于。下面是一篇关于这个主题的好文章:欢迎使用堆栈溢出!谢谢你的回复!请务必仔细阅读本手册。另外请注意,每次链接到自己的站点/产品时,都需要发布免责声明。关注点:js区分大小写。您的大写锁定示例不起作用;-)此外,还可以有一个命名的IIFE:(函数myFunc(){…}())代码>编写IIFE的较短且广泛使用的方法:如果您不关心返回值,或者不关心使代码更难阅读的可能性,那么只需在函数前面加上一元运算符,就可以节省一个字节。示例:!函数(){/*代码*/}()
(来源:)@naXa-+1链接,关于IIFE的文章写得很好:)最后一篇与var foo=function(){return 5;}
不同。因为这里,foo.name
是'
,最后一个是