前言

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个:

  1. (5 + 1) * 2 ,这段代码自身就是表达式,产生的值为12
  2. (5 + 1) ,因为有括号,这个子表达式首先求值,并解析为6
  3. 5,单个数字自身就是表达式,因为它们产生一个值。这个表达式解析为5
  4. 1,同样的情理,这个表达式解析为1
  5. 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));

这种区别可能须要一段时间能力变得不言而喻,心愿这篇文章能够帮忙到你。

以上就是本文的所有内容,欢送点赞珍藏转发~