函数声明Vs函数表达式



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)我如何理解函数bar在括号中的语法?var x = (function bar() {return 1})var x = function bar() {return 1}有什么不同?

在MDN页面的评论是非常误导。(MDN是一个协作编辑的参考文献。通常都很好。)

从上面的例子中,

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

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

直到ES2015(又名"ES6"),它们都是未指定行为,因为它们是控制流块中的函数声明。规范没有定义如何处理它们,但是在规范下处理它们是一个"允许的扩展",并且一些引擎确实支持它们。不幸的是,不同的引擎通过做不同的事情来支持它们

但是在ES2015中,规范接受了它们:它们仍然是函数声明,但是如何解释取决于是否…

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

因为在松散模式下你不能确定JavaScript引擎是要实现附件 B行为还是非附件 B行为,唯一合理的选择是:

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

如果您使用严格模式(无论是否在浏览器上),行为非常简单:声明被提升到其块的顶部,并且是块作用域(如letconst)。由声明创建的标识符是可写的,因此它是,就好像声明被转换为赋值给块顶部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);
}

有效地变成了:

// NOT in strict mode
function example() {
    var world;
    if (x) {
        world = function world() {};
        console.log("testing:");             // testing: (if executed)
        console.log("1:", typeof world);     // 1: function (if executed)
        console.log("2:", typeof world);     // 2: function (if executed) 
    }
    console.log("3:", typeof world);        // 3: function if `x` is truthy, undefined if `x` is falsy
    console.log("4:", world === undefined); // 4: false if `x` is truthy, true if `x` is falsy
}

最新更新