共计 2994 个字符,预计需要花费 8 分钟才能阅读完成。
前言
JavaScript 中的语句和表达式有什么不同之处?
对于这个问题,我仿佛晓得答案,但当我尝试向他人解释时,我却语塞了。对于这个问题我有一种感觉,但无奈清晰的表达出来。
我起初才意识到,这个问题极其重要。它能够说是屋宇的承重墙,将有助于撑持大量的 JavaScript 常识。
对 React 开发者来说,更为如此。你不得不记住的那些 JSX 规定,以及总是遗记恪守的那些规定,大部分都是 语句 / 表达式 双重性的后果。
在这篇文章中,我将分享我对这两者区别的一些感悟,以及咱们如何在日常工作中应用这些信息。
表达式
从实质上来说,表达式是产生值的一段 JavaScript 代码。
上面所有的例子全部都是表达式:
1
→ 产生值为1
"hello"
→ 产生值为"hello"
5 * 10
→ 产生值为50
num > 100
→ 产生值为true
或者false
isHappy ? "🙂" : "🙁"
→ 产生值为一个 emoji[1, 2, 3].pop()
→ 产生值为3
表达式能够蕴含其余表达式。举例来说,你感觉上面的 JS 代码中有多少个表达式?
(5 + 1) * 2
答案是一共有 5 个表达式。
具体来说,别离是以下 5 个:
(5 + 1) * 2
,这段代码自身就是表达式,产生的值为12
(5 + 1)
,因为有括号,这个子表达式首先求值,并解析为6
。5
,单个数字自身就是表达式,因为它们产生一个值。这个表达式解析为5
。1
,同样的情理,这个表达式解析为1
。2
,这个数字造成最初的表达式,它解析为2
。
语句
一个 JavaScript 程序是一连串的语句。每条语句都是计算机做某件事的指令。
这里是无关 JavaScript 中语句的示例:
let hi = 5;
if (hi > 10) {// 更多语句}
throw new Error('报错了');
对于语句和表达式,我是这么认为的:语句是撑持咱们程序的刚性构造,而表达式则填充了细节。
语句中通常有表达式的 “ 插槽 ”。咱们能够把任何咱们喜爱的表达式放到这些插槽里。
举例来说,申明一个具备表达式插槽的变量能够这么做:
let hi = /* 表达式 */;
在这个插槽中,咱们能够应用任何先前看到过的表达式:
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" 永不扭转,因而循环会一遍又一遍的反复,直到脚本解体。// 语法上是无效的,但仍是有问题的。}
便捷技巧
想晓得一段 JS 代码到底是语句还是表达式吗?试着将它打印进去吧!
console.log(/* 这里是 JS 代码 */);
如果可能运行,该代码就是表达式。如果报错,那就是语句(当然,也有可能是非法 JS)。
此外,咱们甚至能够看到表达式的后果,因为会将后果打印到浏览器的控制台中。
这样能够凑效是因为任意函数的参数都必须是表达式。表达式会产生一个值,并将该值传递到函数中。语法并不会产生一个值,因而语句不能被用作函数的参数。
即便作为一个有教训的开发者,我也十分依赖console.log
。它真的是一个好货色。
表达式作为语句
这是一个表达式:1 + 2 + 3
。
如果咱们创立一个只包含这个表达式的 JS 文件,会产生什么?让咱们试想把上面的内容保留为test.js
:
1 + 2 + 3
该文件中有多少个语句?0 个还是 1 个?
事件是这样的:表达方式不能独自存在。它们总是语句的一部分。所以在这种状况下,咱们有一个看起来像这样的语句:
/* 表达式插槽 */
除了表达式插槽之外,该语句基本上是空的。表达式 1 + 2 + 3
填充了该插槽,那么语句也就生成了。
换句话说,以下所有行都是无效的语句:
// 语句 1:
let hi = /* 表达式插槽 */;
// 语句 2:
return /* 表达式插槽 */;
// 语句 3:
if (/* 表达式插槽 */) { }
// 语句 4:
/* 表达式插槽 */
通常状况下,某些教程会谬误地指出,表达式就是语句,但这并不完全正确。表达式和语句是不同的货色。然而语句有可能在不提供任何额定字符的状况下包裹住表达式。这就如同用通明的保鲜膜包裹住一个三明治。
语句通常以分号结尾,它标记着语句的完结。对某些语句来说分号不是必须的,如 if
语句、while
循环和函数申明。
React 中的实际
如果你曾应用过 React,你可能晓得大括号 {
和}
容许咱们在 JSX 中嵌入一些 JavaScript,就像这样:
function CountdownClock({secondsRemaining}) {
return (
<div>
Time left:
{Math.round(secondsRemaining / 60)} minutes!
</div>
);
}
这就是 React 的神奇之处,它能够让咱们领有 JavaScript 的全副能力。
但有一个问题 — 咱们不能在大括号外面搁置任意 JavaScript 代码。具体来说,咱们只能包含表达式,而不能包含语句。大括号实质上是在咱们的 JSX 中创立一个表达式插槽。
如果咱们尝试在大括号内嵌入一个语句,比如说 if/else
语句,咱们会失去谬误:
function CountdownClock({secondsRemaining}) {
return (
// 🚫 语法报错
<div>
{if (secondsRemaining > 0) {`${secondsRemaining} seconds left`
} else {"Time expired!"}}
</div>
);
}
这是因为语句不会产生值,只有表达式才会产生值。如果咱们想在 JSX 中嵌入 if/else
逻辑,咱们须要应用一个三元操作符表达式:
function CountdownClock({secondsRemaining}) {
return (
// ✅ 没问题
<div>
{secondsRemaining > 0
? `${secondsRemaining} seconds left`
: "Time expired!"
}
</div>
);
}
这仿佛是一个诡异的 JSX/React 限度,但它实际上是一个 JavaScript 限度。
我想咱们常常嗔怪 React 的一些看似果断的规定,比方组件必须返回一个顶层元素。但更多的时候,React 只是在正告咱们一个对于 JavaScript 的限度。
了解语句和表达式的区别是十分重要的。咱们还须要理解 JSX 是如何编译成 JavaScript 的,以及 React 的调度与渲染周期是如何工作的 …… 然而,这些话题曾经超出了本篇文章的范畴。
总结
一个 JavaScript 程序由一连串的语句组成。每个语句都是做某件事的指令,比如说,创立一个变量,运行一个 if/else
条件语句,或者开始一个循环。
表达式产生一个值,这些值被放入语句的插槽内。表达式始终是语句的一部分,即便该语句是空的。例如,上面的代码在运行一个循环时没有应用 for
语句,但它依然蕴含一个”通明保鲜膜”语句:
data.forEach(item => console.log(item));
这种区别可能须要一段时间能力变得不言而喻,心愿这篇文章能够帮忙到你。
以上就是本文的所有内容,欢送点赞珍藏转发~