函数声明与函数表达式

时间:2015-08-22 10:51:21

标签: javascript

MDN给出了一些示例,如下所示,

// function declaration
function foo() {}

// function expression
(function bar() {})

// function expression
x = function hello() {}


if (x) {
   // function expression
   function world() {}
}


// function declaration
function a() {
   // function declaration
   function b() {}
   if (0) {
      // function expression
      function c() {}
   }
}

根据定义,表达式的计算结果为。

从上面的例子中,

1)函数world是表达式还是声明?因为world看起来像声明声明

2)函数c是表达式还是声明?因为c看起来像声明声明

3)如何理解paranthesis中函数bar的语法? var x = (function bar() {return 1})var x = function bar() {return 1}有何不同?

1 个答案:

答案 0 :(得分:3)

MDN页面中的评论非常具有误导性。 (MDN是一个经过协作编辑的参考文献。它通常非常出色。有时它会有点不足。)

  

从上面的例子中,

     

1)函数世界是表达式还是声明?

     

2)函数c是表达式还是声明?

直到ES2015(又名“ES6”),它们都是未指定的行为,因为它们是控制流块中的函数声明。规范没有定义它们应该如何处理,但处理它们是spec(blech)下的“允许扩展”,一些引擎确实支持它们。不幸的是,不同的引擎通过不同的东西来支持它们。

从ES2015开始,规范将其引入:它们仍然是函数声明,但它们如何被解释而变化取决于...

  • ...代码处于严格模式(行为合理且直接),
  • ...代码在浏览器托管的JavaScript引擎上处于松散模式,该引擎实现了规范Annex B.3.3Annex B.3.4所描述的可选旧行为(令人困惑) ,并且只有几个安全的跨浏览器场景,
  • ...或者代码是否在非浏览器JavaScript引擎上处于松散模式,理论上 不应该实现附件B(但这并不能阻止它们)。

由于在松散模式下您无法确定JavaScript引擎是否将实施附件B行为或非附件B行为,因此唯一合理的选择是:

  • 使用严格模式或
  • 不要使用块级函数声明。

如果您使用严格模式(无论是否在浏览器上),行为非常简单:声明被提升到其块的顶部并且是块范围的(如let和{{1} } 是)。声明创建的标识符是可写的,因此就好像声明被转换为分配给块顶部的const变量的函数表达式。我们来看let示例,但添加一些。

此:

world

... 有效地成为了这个:

"use strict";
// ...
function example() {
    if (x) {
        console.log("testing:");
        console.log("1:", typeof world);
        function world() {}
        console.log("2:", typeof world);
    }
    console.log("3":, typeof world);
    console.log("4:", world === undefined);
}

注意声明如何被提升到块的顶部,并且是块范围的。

在严格模式之外,这取决于,但非遗留版本就像严格模式"use strict"; // ... function example() { if (x) { let world = function world() {}; console.log("testing:"); // testing: console.log("1:", typeof world); // 1: function console.log("2:", typeof world); // 2: function } console.log("3:", typeof world); // 3: undefined console.log("4:", world === undefined); // ReferenceError: `world` is not defined } 而不是var

所以:这个:

此:

let

... 有效地成为了这个:

// NOT in strict mode
function example() {
    if (x) {
        console.log("testing:");
        console.log("1:", typeof world);
        function world() {}
        console.log("2:", typeof world);
    }
    console.log("3":, typeof world);
    console.log("4:", world === undefined);
}