根据
MDN的说法:
表达式是任何可以解析为一个值的有效代码单元。
因此,任何可以用作右值的东西都是表达式。
标准并不是副作用是否存在。 表达式肯定可以具有副作用。 例如,
a=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
包含其中一个函数表达式,而第二种情况下,它包括了等效的函数声明:
{
let i = 0;
try {
function f () {
i++;
(function g() {})();
f();
}
f();
} catch (err) {
console.log(`Function Expressions case: depth of ${i} reached. Error: ${err.name}`);
}
}
{
let i = 0;
try {
function f () {
i++;
function g() {};
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
…这与函数声明会增加执行上下文所需空间并因此稍微更快地消耗堆栈空间,从而略微降低最大递归深度的事实是一致的。
eval
函数来执行 JavaScript 代码,这让我认为在 JavaScript 中所有语句都是表达式。 - Sidharth Mudgaldo
-while
循环会在结束后重复最后一个值?。 - Sebastian Simon