JavaScript:声明与表达式vs语句

时间:2017-09-21 19:35:39

标签: javascript expression

在过去的几个小时里,我一直试图找到3之间的差异,而不仅仅是差异,我也一直试图找出哪种是同义词,MDN调用所有声明"语句&#34 ;所以我认为这是真的。但是,我读过的所有文章和SO问题都没有为我提供各种各样的备忘单来区分3(或2,表达式与陈述)。

我在语句中注意到的一点是,它们都以某种方式涉及特殊的JavaScript关键字,例如breakforvar。文章说,表达式评估某些内容,而语句执行操作。什么是功能呢?它是一个语句表达式混合(因为它在调用时都执行一个动作,并返回一个值)?现在,我假设情况并非如此,因为函数调用不涉及JavaScript关键字。

然后有声明,是每个声明也是一个声明?

我也知道像20 + 5 * 2 / 3;这样的表达语句,但这些几乎没用吗?为什么有人会用这样的行污染他们的代码?

如果有人可以提出上述问题(或者至少其中一些问题),或者有人可以提供某种类型的备忘单,我会非常高兴。为什么在如此流行的语言中,关于某个主题的材料如此简单呢?

3 个答案:

答案 0 :(得分:6)

这些术语的标准定义包括所有语言,包括JS。我对它们的看法如下:

  • 表达式生成一个值,可以在期望值的任何地方写入。

  • 另一方面,陈述是一个独立的执行单位。它不会返回任何内容。

  • 声明是一个声明,其中为变量赋值。

  • 所有声明都是声明,但并非所有声明都是声明。

  • 大多数陈述和所有声明都包含表达式。

Javadoc也提供了很好的,简洁的定义:

  

表达式是由变量,运算符和方法调用组成的构造,它们是根据语言的语法构造的,其值为单个值。

     

陈述大致相当于自然语言中的句子。声明构成了一个完整的执行单元。

现在,关于必然涉及的关键字的理论是不正确的。这是一个包含关键字的语句:

break;

这是一个没有:

foo();

在第一个例子中,我执行break,而在第二个例子中,我调用一个函数。两者都是语句,但只有一个包含任何特殊关键字。

函数不是声明。函数调用是一个语句,如上所示。对于返回某事的函数,该调用也可以是声明:

var bar = foo();

对于你的最后一个问题,那里的材料很少的原因是因为这仅仅是一个语义问题。人们不会徘徊在这些术语的确切定义上。

为了进一步澄清,我建议您查看Axel Rauschmayer的this博客文章,该文章专门讨论了JS中语句和表达式之间的区别。

答案 1 :(得分:2)

  

在过去的几个小时里,我一直试图找到3之间的差异,而不仅仅是差异,我也一直试图找出哪种是同义词,MDN调用所有声明"语句&#34 ;所以我认为这是真的。

声明是"声明"的任何结构。在程序执行之前的编译/加载时存在的变量名。因此,各自范围内的所有声明的名称都是事先已知的。

陈述和表达方式彼此不同,前者不会产生价值,而后者则产生价值。因此,可以在期望值的任何地方使用表达式,并且可以不在那些地方使用语句。

表达式语句是语句是单个表达式的表达式,或者是包含在需要零个或多个子表达式的表达式中的表达式语句。虽然表达式产生了结果,但声明却没有。

这是一个表达式:

x = foo() + 2

可以通过在末尾添加分号来明确显示完整表达式语句。

x = foo() + 2;

第一个示例可以包含在一组parens中,因为作为分组运算符的parens需要一个表达式,通常由逗号运算符连接的几个表达式提供。

第二个示例不能包含在parens中(如果包含分号),因为它是一个语句,并且不会产生一个值,分组操作符期望接收该值并将其作为自己的值返回。

  

我在语句中注意到的一点是它们都以某种方式涉及一个特殊的JavaScript关键字,如break或for或var。

虽然大多数语句确实涉及关键字,但并非所有语句都涉及。最值得注意的是,block语句没有关键字。相反,它使用一组花括号来分隔它的开始和结束。

  

文章说,表达式会评估某些内容,而语句会执行操作。什么是功能呢?它是一个语句表达式混合(因为它在调用时都执行一个动作,并返回一个值)?现在,我假设情况并非如此,因为函数调用不涉及JavaScript关键字。

JS中有三种功能。如果您正在谈论使用function关键字的那些,那么根据其上下文,它可以是声明或表达式。

如果在期望表达式的地方使用该函数,则将其计算为返回新函数对象的表达式。如果没有,那么它应该是一个声明,它基本上创建一个赋值给它的函数对象的变量。作为声明,函数名称​​ required (对于变量名称)。作为表达,它是可选的。

  

我也知道像20 + 5 * 2 / 3;这样的表达语句,但这些几乎没用吗?为什么有人会用这样的行污染他们的代码?

如果结果值被忽略,那么在给定示例的情况下它将是无用的。但这是另一个表达陈述。

foobar();

现在我们有一个函数调用的副作用,这很可能是期望和有用的。

答案 2 :(得分:2)

我们首先谈谈表达式。正如你所说,表达式是一个计算值的东西。函数是一个值。另一方面,函数调用是一个表达式。

我不同意将声明描述为“执行行动”的内容。正如你所说,调用一个函数涉及运行函数体,它由语句和声明组成,因此它在“内部”执行动作。

更好的方法是查看表达式,语句和声明是语法类别。它们源于试图描述JavaScript语法的结构。参见例如expressions上的ECMAScript 8规范,statements, and declarations

20 + 5 * 2 / 3;这样的表达式语句确实没用,因为它没有任何效果,而声明的唯一要点就是它的效果。但是还有其他更有用的表达式语句:

  • 函数调用:foo();
  • 赋值:x = 42;=是一个运算符,可以在表达式中使用)
  • 递增/递减:i++;(类似地,++是运营商)

表达式语句以外的语句倾向于以特殊关键字开头,以避免语法歧义:解析器希望能够从一开始就告诉它正在处理什么类型的构造。因此我们得到:

  • if statements:if (EXPR) STMT
  • while声明:while (EXPR) STMT
  • 返回语句:return;return EXPR;

但是,有些语句不是以关键字开头的:

  • 空语句:;
  • 一个街区:{ ... }

最后,声明。在JavaScript中,语句和声明之间的区别有些武断。语法区分两者,但在实践中,您通常可以将它们视为相同(例如,块语句的内容被定义为语句列表项的序列,并且语句列表项被定义为是声明或声明)。声明包括:

  • 函数声明:function foo() { ... }(包括诸如生成器(function* foo() { ... })和异步函数(async function foo() { ... })之类的变体)
  • letconst
  • class声明

(但出于某种原因,var foo;被归类为陈述,而不是声明。)