前言
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));
这种区别可能须要一段时间能力变得不言而喻,心愿这篇文章能够帮忙到你。
以上就是本文的所有内容,欢送点赞珍藏转发~