Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript中的函数表达式和声明有什么区别?_Javascript - Fatal编程技术网

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
    '
    ,最后一个是