函数表达式与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(){}与function functionName(){}的回答有什么不完全正确?

杨天栾2020/03/12 20:38:29

功能声明

function foo() { ... }

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

函数表达式

  1. 命名函数表达式

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

    var foo = function() { ... }
    

foo() 创建后才能调用。

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

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

结论

Crockford建议使用函数表达式,因为它可以清楚地表明它foo是一个包含函数值的变量。好吧,就我个人而言,除非有理由表达,否则我更喜欢使用声明。

理查德十三Davaid2020/03/12 20:38:29

尽管完全的区别更加复杂,但是与我有关的唯一区别是机器创建功能对象时。在声明的情况下,这是在执行任何语句之前但在调用语句主体之后(是全局代码主体或子函数的那个​​),在表达式的情况下,是执行该语句所在的语句时。出于所有意图和目的,浏览器均将它们视为相同。

为了帮助您理解,请看一下此性能测试测试否定了我对内部声明的函数所做的假设,当调用外部函数时,不需要由机器重新创建内部声明的函数。我也很喜欢那样写代码,这也有点可耻。

村村小小十三2020/03/12 20:38:29

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

如果在全局上下文中声明,它将创建一个称为“ foo”的隐式全局变量,该变量将指向该函数。因此,可以在您的javascript程序中的任何位置进行函数调用“ foo()”。

如果函数是在闭包中创建的,则会创建一个隐含的局部变量“ foo”,您可以使用该变量通过“ foo()”在闭包内调用该函数。

编辑:

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

结束编辑

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

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

是相同的

var foo = function fooYou() { return 5; }
2020/03/12 20:38:29

关于第三个定义:

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