根据MDN:
表达式是解析为值的任何有效代码单元。
因此,任何可以用作右值的东西都是一个表达式。
标准不是副作用是否存在。表达式肯定会产生副作用。ega=2
是一个表达式,因为它有一个值 (2) 并且还为一个变量赋值。这就是为什么您可以执行以下操作:
let a;
let b = 1 + (a = 2); // a is now 2 and b is 3
根据上下文,可以将相同的(文本)代码块视为表达式和语句。例如,文本片段function f(){}
是下面代码中第 1 行的表达式和第 2 行的语句:
let g = function f() {};
function f() {};
因此,不能(在一般情况下)通过脱离上下文查看一段文本代码来确定某事物是表达式还是语句;相反,它是语法树中节点的属性,只有在(精神上或实际上)解析代码后才能决定。
此外,也许更重要的是,函数内的函数语句(又名函数声明)f
构成了在f
调用函数时创建的执行上下文的一部分。但是,函数表达式不构成该执行上下文的一部分。
一个经常被引用的效果是函数声明被“提升”而函数表达式不会。
考虑到函数语句在执行上下文中占用空间而函数表达式不占用空间,在深度递归中也可以通过实验观察到更微妙的效果。例如,下面的代码使用函数的无限递归f
。f
第一种情况下的函数在其中包含一个函数表达式,在第二种情况下它包括等效的函数声明:
// Function Expression
{
let i = 0;
try {
function f () {
i++;
(function g() {})(); // this is an expression
f();
}
f();
} catch (err) {
console.log(`Function Expressions case: depth of ${i} reached. Error: ${err.name}`);
}
}
// Function Declaration
{
let i = 0;
try {
function f () {
i++;
function g() {}; // this is a statement
g();
f();
}
f();
} catch (err) {
console.log(`Functions Declarations case: depth of ${i} reached. Error: ${err.name}`);
}
}
在我的机器上,我始终得到以下信息(在 node.js 中):
Function Expressions case: depth of 17687 reached. Error: RangeError
Functions Declarations case: depth of 15476 reached. Error: RangeError
...这与函数声明增加了保存执行上下文所需的空间量并因此更快地消耗堆栈空间并因此略微降低最大递归深度的事实一致。