原文链接:www.joshwcomeau.com/javascript/…
作者:Joshua Comeau
声明 VS 表达式
去年面试时,一个面试官问我:
JavaScript 中的语句和表达式有什么区别?
我讲不清他两准确的区别😅,只能举了几个例子说明这是表达式,这是语句,这是表达式。
面试结束后我决定,好好的搞清楚他们。
对于 React 开发人员
如果您使用过 React,您可能知道花括号( { 和 } )允许我们在 JSX 中嵌入一些 JavaScript,如下所示:
function Demo() {
return (
<div>
{1+1}
</div>
);
}
如果我们尝试在此处嵌入一个语句,例如 if/else 语句,我们将得到一个错误:
function Demo() {
return (
// 🚫 抛出一个错误
<div>
{if (1 > 0) {
`正确的`
} else {
"错误的"
}}
</div>
);
}
很多开发者认为这是一个奇怪的 JSX/React 限制,
但它实际上是一个 JavaScript 限制。
因为在JSX中是不能插入语句,只能插入表达式。很多开发者遇到这个问题,都仅是记住他,并没有深入的去研究他。
在这篇文章中,我将分享我对这种区别的一些顿悟,以及我们如何在日常工作中使用。
Expressions 表达式
表达式的核心是能生成一些值的 JavaScript 代码。
例如,这些都是表达式:
1→ 生成1"hello"→ 生成"hello"5 * 10→ 生成50num > 100→ 生成true或falseisHappy ? "🙂" : "🙁"→ 生成表情符号[1, 2, 3].pop()→ 生成数字3
Statements 语句
JavaScript 程序就是一系列语句。每条语句都是让计算机做某事的指令。
例如,这些都是语句:
let hi = 5;
if (hi > 10) {
// More statements here
}
throw new Error('Something exploded!');
我喜欢将他们想象成:语句是将我们的程序的结构,而表达式则填充细节。
语句通常有表达式的槽。我们可以将任何表达式放入这些插槽中。
例如,声明一个有表达式槽的变量:
let hi = /* some expression */;
我们可以在槽中插入的任何表达式:
let hi = 1;
let hi = "hello";
let hi = 5 * 10;
let hi = num > 100;
let hi = isHappy ? "🙂" : "🙁";
let hi = [1, 2, 3].pop();
就有效语法而言,表达式是可以互换的。如果一个语句有一个表达式槽,我们可以把任何表达式放在那里。
但是我们要注意一点:代码有效不代表可以运行,代码在语法上是有效的,但如果我们运行它,浏览器就会崩溃,因为它会导致无限循环,例如:
while ("hello") {
// 因为“hello”没有改变,循环会一直运行
}
如何判断呢?
使用console.log()就能知道一段 JS 代码是表达式还是语句
console.log(/* 这有一些JS的代码 */);
如果它运行,代码就是一个表达式。如果你得到一个错误,它是一个语句(或者,可能是无效的 JS)。
我们甚至可以看到表达式解析的内容,因为它将打印在浏览器控制台中!
为何可行呢?
因为所有函数参数都必须是表达式。表达式产生一个值,该值将传递给函数。语句不产生值,因此不能用作函数参数。
没想到用 console.log 解决了这个问题吧!
Expressions as statements 表达式作为语句
这是一个表达式: 1 + 2 + 3 。
如果我们创建一个只包含这个表达式的 JS 文件会发生什么?假设我们将以下内容保存为 test.js :
1 + 2 + 3
这个文件有多少条语句?零还是一个?
要知道:表达式不能单独存在。它们始终是声明的一部分。所以在这种情况下,我们有一个看起来像这样的声明:
/* 表达式槽 */
除了它的表达式槽外,该语句是空的。我们的表达式 1 + 2 + 3 填充了这个槽,我们的语句就完成了。
换句话说,以下所有行都是有效的语句:
// 语句 1:
let hi = /* 表达式槽 */;
// 语句 2:
return /* 表达式槽 */;
// 语句 3:
if (/*表达式槽 */) { }
// 语句 4:
/* 表达式槽 */
通常,很多教程会错误告诉大家表达式就是语句,但这并不完全正确。
表达式和语句是不同的东西。只能说语句在没有额外字符的情况下包裹着表达式,他两才一致。
可以把它想象成用透明收缩包装纸包裹三明治。
语句通常以分号结尾,分号表示语句结束。某些语句不需要分号,例如 if 语句、 while 循环和函数声明。
还记得上面那个React的if else代码吗
如果我们想在我们的 JSX 中嵌入 if/else 逻辑,我们需要使用三元运算符表达式:
function Demo() {
return (
// ✅ 没问题
<div>
{1 > 0
? `正确的`
: "错误的"
}
</div>
);
}
这可能看起来像是一个奇怪的 JSX/React 限制,但它实际上是一个 JavaScript 限制。
我认为我们经常责怪 React 看似武断的规则,比如组件必须只能返回一个标签。
但通常情况下,React 只是警告我们 JavaScript 的限制。
总结
-
JavaScript由一系列语句组成。每个语句都是执行某项操作的指令,例如创建变量、运行 if/else 条件或启动循环。 -
表达式产生一个值,这些值被放入语句中。
-
表达式始终是语句的一部分,即使该语句在其他方面为空。
例如,下面的代码在不使用 for 语句的情况下运行一个循环,它仍然包含一个空包裹器的语句:
data.forEach(item => console.log(item));
最后希望你理解了这两者的区别!
全文完。
谢谢!
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 6 天