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}
有何不同?
答案 0 :(得分:3)
MDN页面中的评论非常具有误导性。 (MDN是一个经过协作编辑的参考文献。它通常非常出色。有时它会有点不足。)
从上面的例子中,
1)函数世界是表达式还是声明?
2)函数c是表达式还是声明?
直到ES2015(又名“ES6”),它们都是未指定的行为,因为它们是控制流块中的函数声明。规范没有定义它们应该如何处理,但处理它们是spec(blech)下的“允许扩展”,一些引擎确实支持它们。不幸的是,不同的引擎通过不同的东西来支持它们。
从ES2015开始,规范将其引入:它们仍然是函数声明,但它们如何被解释因而变化取决于...
由于在松散模式下您无法确定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);
}