根据MDN:
表达式是解析为值的任何有效代码单元。
因此,任何可以用作右值的东西都是表达式。
标准是不是否存在副作用。表达式肯定会产生副作用。例如。 a=2 是一个表达式,因为它有一个值 (2) 并且还为一个变量赋值。这就是为什么您可以执行以下操作:
let a;
let b = 1 + (a = 2); // a is now 2 and b is 3
根据上下文,同一(文本)代码块可能同时被视为表达式和语句。例如。文本 sn-p 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
...这与函数声明增加了保存执行上下文所需的空间量并因此更快地消耗堆栈空间并因此略微降低最大递归深度的事实是一致的。