之前我问过这个问题,又想了想这个话题,我开始怀疑“陈述”和“表达”这两个术语的含义之间看似模糊的界限在哪里。所有语句都是表达式吗?REPL 控制台中的返回值来自哪里?它们似乎并不总是具有任何直观意义。当然,如果你输入1+1
,你会得到2
,但其他时候逻辑是什么就不那么明显了。
鉴于输入到 REPL 中的任何内容都会产生一些值,这是否意味着它可以在 JS 源代码中用作表达式和独立语句?
可以在以下代码段中使用的代码字符串_X_
也可以用于_Y_
反之亦然?if(_X_) _Y_
之前我问过这个问题,又想了想这个话题,我开始怀疑“陈述”和“表达”这两个术语的含义之间看似模糊的界限在哪里。所有语句都是表达式吗?REPL 控制台中的返回值来自哪里?它们似乎并不总是具有任何直观意义。当然,如果你输入1+1
,你会得到2
,但其他时候逻辑是什么就不那么明显了。
鉴于输入到 REPL 中的任何内容都会产生一些值,这是否意味着它可以在 JS 源代码中用作表达式和独立语句?
可以在以下代码段中使用的代码字符串_X_
也可以用于_Y_
反之亦然?if(_X_) _Y_
所有语句都是表达式吗?
“只要 JavaScript 需要一个语句,你也可以写一个表达式。这样的语句称为表达式语句。反过来不成立:你不能在 JavaScript 需要表达式的地方编写语句。例如,if 语句不能成为函数的参数。”</p>
这来自 Axel Rauschmayer 最近关于该主题的一篇文章: JavaScript 中的表达式与语句
希望能帮助到你。
根据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
…这与函数声明增加了保存执行上下文所需的空间量并因此更快地消耗堆栈空间并因此略微降低最大递归深度的事实是一致的。
用最简单的术语来说,表达式被求值以产生一个值。另一方面,执行语句以使某些事情发生。
表达式产生或评估一些值。
表达式示例:
new Date()
生成没有任何副作用的新 Date 对象。
[1,2,3]
产生一个没有任何副作用的新数组。
5+6
产生一个新值 11.它只是产生新值而没有任何副作用。
语句产生一些行为或做某事,它也有一些副作用。根据副作用,可以对语句进行分类。
x=5;
是一个语句,这里的副作用是 x 的赋值或更改。
setTimeout()
- 计时器的开始是副作用。
语句一般用分号隔开。
表达式语句是具有某些副作用的表达式或简称为“具有副作用的表达式”。
表达式语句示例:
x+=6;
是复杂表达式(主要表达式组)正在做赋值,这是一个副作用,所谓的表达式语句。
delete a[2];
表达式:解析为值的代码单元,例如,文字和运算符。表达式示例:
> 3
> 1 + 2
> "expression"
> fn()
> []
> {}
语句:表示一条或多条指令的代码单元,通常以语言保留关键字开头,显式或隐式地以语句终止符结束。语句示例:
> 3;
> let x = 3;
> if () {}
> for () {}
> while () {}
JavaScript 中的所有程序都是由语句组成的,它们以分号结尾,除了用于对零个或多个语句进行分组的块语句。语句只是执行一些操作,但不产生任何值或输出,而表达式返回一些值。当解释器看到一个表达式时,它会检索它的值并用新值替换表达式。语句用于操作这些表达式。您可以在此处检查它是表达式还是语句:JavaScript Parser
转到浏览器控制台(Ctrl + Shift + I
或Command + Shift + I
):
输入对您来说不明确的代码。
如果浏览器undefined
在每行执行后返回,它就是一个语句。
undefined
如果浏览器在每行执行之后返回任何值,则它是一个表达式。
浏览器控制台的行为就像它console.log(statement)
用于输入的每一行代码一样。请参阅此以获取更多信息。
此程序仅用于验证。
但有必要了解:
表达式return
值,语句没有。
所有的表达式都是陈述,但不是其他的。您不能使用语句代替表达式。
我强烈建议阅读 Axel Rauschmayer 博士的综合博文
Expressions vs statements in JavaScript
,如上面@ZER0 接受的答案中所述。
但我最喜欢的记忆捷径是:
表达式:
e
可以设置E
为Expression
.. 或Expressed
通过打印它。
陈述:
..还有什么。
以下是从
Anders Kaseorg 的 Quora 回答中修改的。
语句是执行某些操作的完整代码行。
E
非常E
xpression 可以用作语句
(其作用是评估表达式,并忽略结果值)。
但是xpressionE
是代码中任何计算为 value 的部分。 e
e
表达式可以使用运算符“水平”组合成更大的表达式。
E
有一个水平平坦的顶部
大多数语句不能用作表达式。
语句只能通过一个接一个地编写或使用块结构来“垂直”组合。
S
相比之下,垂直运行。
这是一个一般的经验法则:如果你可以打印它,或者将它分配给一个变量,它就是一个表达式。如果你不能,这是一个声明。
以下是一些表达式示例:
2 + 2
3 * 7
1 + 2 + 3 * (8 ** 9) - sqrt(4.0)
min(2, 22)
max(3, 94)
round(81.5)
"foo"
"bar"
"foo" + "bar"
None
True
False
2
3
4.0
以上所有内容都可以打印或分配给变量。
以下是一些陈述示例:
if CONDITION:
elif CONDITION:
else:
for VARIABLE in SEQUENCE:
while CONDITION:
try:
except EXCEPTION as e:
class MYCLASS:
def MYFUNCTION():
return SOMETHING
raise SOMETHING
with SOMETHING:
上述构造都不能分配给变量。它们是服务于目的的句法元素,但它们本身没有任何内在的“价值”。换句话说,这些结构不会“评估”任何东西。例如,尝试执行以下任何操作都是荒谬的,而且根本行不通:
x = if CONDITION:
y = while CONDITION:
z = return 42
foo = for i in range(10):
产生值的代码片段称为表达式。每个字面书写的值(例如 22 或“精神分析”)都是一个表达式。括号之间的表达式也是一个表达式,就像应用于两个表达式的二元运算符或应用于一个表达式的一元运算符一样。
一个表达式对应人类语言中的一个句子片段,一个 JavaScript 语句对应一个完整的句子。程序是语句的列表。
最简单的语句是后面有分号的表达式。这是一个程序:
1个;!错误的; 不过,这是一个无用的程序。表达式可以满足于只产生一个值,然后可以由封闭代码使用。一个声明是独立存在的,因此只有当它影响到世界时,它才算是某种东西。
声明可能有副作用。
让我向您展示一些幼稚的例子。
以下代码定义了一个value
. 它是一个由关键字引导的statement
调用。这是一个.let statement
let
1
expression
// statement
// |---------|
let n = 1 ;
// |-|
// expression
这是for statement
由for
关键字引导的。它带有一些嵌套的表达式和语句。
// expression(1)
// |-----------|
for (num in numArr) { //--+
// |
sum += (num * 3); // statement(2) // |
// |-----| // |statement(1)
// expression(2) // |
// |
} //--+
所以 astatement
是一个指令单元,告诉计算机要做什么。for statement
, while statement
, if statement
, 它们都是动作,换句话说就是任务,或者行为。
但是对于expression
,我们谈论的是值、贵重物品、对象或一些可以产生值的过程,如函数。
1 + 2
(2 + 3) * 5 === 25
new Foo()
所以 Javascript 也有function expression
. 因为function
是一个value
。在下面的代码中,
=
都是一种表达。return width * height;
是嵌套语句。width * height
是一个表达式。const rectArea = function(width, height) {
return width * height;
};