Javascript:语句和表达式之间的区别?

IT技术 javascript expression terminology semantics
2021-03-22 12:22:47

之前问过这个问题,想了想之后,开始思考“statement”和“expression”这两个术语的含义之间看似模糊的界限在哪里。所有的语句都是表达式吗?REPL 控制台中的返回值从何而来?它们似乎并不总是具有任何直觉意义。当然,如果你输入1+1,你会得到2,但其他时候它的逻辑并不那么明显。

鉴于输入到 REPL 中的任何内容都会产生一些值,这是否意味着它可以在 JS 源代码中用作表达式和独立语句?

可以_X_在以下代码段中使用的代码字符串也可以用于,_Y_反之亦然吗?if(_X_) _Y_

6个回答

所有的语句都是表达式吗?

“在 JavaScript 需要语句的地方,你也可以写一个表达式。这样的语句称为表达式语句。反过来不成立:您不能在 JavaScript 需要表达式的地方编写语句。例如,if 语句不能成为函数的参数。”

这是来自 Axel Rauschmayer 最近关于此主题的帖子: JavaScript 中的表达式与语句

希望能帮助到你。

有兴趣了解有关 javascript 语句和表达式的更多信息的人的一些进一步阅读,即。差异、关键字等:developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/...以及developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
2021-04-22 12:22:47
您不能将有效表达式写{"x": 2}为语句,除非您将其括在括号中。
2021-04-30 12:22:47

根据MDN

表达式是解析为值的任何有效代码单元。

因此,任何可以用作右值的东西都是一个表达式。

标准不是副作用是否存在。表达式肯定会产生副作用。ega=2是一个表达式,因为它有一个值 (2) 并且还为一个变量赋值。这就是为什么您可以执行以下操作:

let a;
let b = 1 + (a = 2); // a is now 2 and b is 3

根据上下文,可以将相同的(文本)代码块视为表达式语句。例如,文本片段function f(){}是下面代码中第 1 行的表达式和第 2 行的语句:

let g = function f() {};
function f() {};

因此,不能(在一般情况下)通过脱离上下文查看一段文本代码来确定某事物是表达式还是语句;相反,它是语法树中节点的属性,只有在(精神上或实际上)解析代码后才能决定。

此外,也许更重要的是,函数内的函数语句(又名函数声明)f构成了在f调用函数时创建的执行上下文的一部分但是,函数表达式构成该执行上下文的一部分。

一个经常被引用的效果是函数声明被“提升”而函数表达式不会。

考虑到函数语句在执行上下文中占用空间而函数表达式不占用空间,在深度递归中也可以通过实验观察到更微妙的效果。例如,下面的代码使用函数的无限递归ff第一种情况下的函数在其中包含一个函数表达式,在第二种情况下它包括等效的函数声明:

// Function Expression
{
    let i = 0;
    try {

        function f () {
            i++;
            (function g() {})(); // this is an expression
            f();
        }

        f();

    } catch (err) {
        console.log(`Function Expressions case: depth of ${i} reached. Error: ${err.name}`);
    }
}
// Function Declaration
{
    let i = 0;
    try {
        function f () {
            i++;
            function g() {}; // this is a statement
            g();
            f();
        }

        f();

    } catch (err) {
        console.log(`Functions Declarations case: depth of ${i} reached. Error: ${err.name}`);
    }
}

在我的机器上,我始终得到以下信息(在 node.js 中):

Function Expressions case: depth of 17687 reached. Error: RangeError
Functions Declarations case: depth of 15476 reached. Error: RangeError

...这与函数声明增加了保存执行上下文所需的空间量并因此更快地消耗堆栈空间并因此略微降低​​最大递归深度的事实一致。

声明和声明是一样的吗?
2021-04-27 12:22:47
这应该是公认的答案。它实际上回答了 OP 问题的所有部分,而且做得非常漂亮。
2021-05-05 12:22:47
深度差异来自不同数量的变量。语句样式在作用域中引入了一个新变量 g,而表达式样式则没有。let g=在表达式之前添加时,则深度将相等
2021-05-12 12:22:47
@Lauri 执行上下文是保存局部变量的内容。函数表达式不会向执行上下文添加任何内容,而函数声明会添加任何内容。另见:stackoverflow.com/a/9384894/274677
2021-05-18 12:22:47
很好的答案!谢谢
2021-05-21 12:22:47

用最简单的术语来说,表达式被求值以产生一个值另一方面,执行语句是为了使某些事情发生

如果我错了,请纠正我,但这不是“表达式语句”吗?我知道也可以评估语句以产生如上所述的值。但是表达式和​​语句之间的区别可以像我上面所做的那样进行总结吗?
2021-04-22 12:22:47
当然,但是这个答案仍然没有添加任何未包含在已接受答案中的内容。
2021-05-04 12:22:47
@Mogsdad 你错了。如果你更仔细地阅读了马库斯所说的“所以,无论是表达式还是语句,都不能(在一般情况下)通过脱离上下文查看一段文本代码来发音;相反,它是一个节点的属性语法树,并且只有在(精神上或实际上)解析代码后才能发音。” 然后你可以意识到 var x = makeSomethingHappen(); 不会产生任何值,因为 var x = whaterver 不会返回任何东西,只有 makeSomethingHappen() 会,但同样,从上面读取 statament...
2021-05-05 12:22:47
除了接受的答案充其量是误导性的。至少这个答案不会误导。
2021-05-06 12:22:47
也可以对语句求值以产生一个值,例如var x = makeSomethingHappen();,所以这个答案是不正确的。(您是否阅读了已接受的答案?已涵盖。)
2021-05-15 12:22:47

表达式产生或评估一些值。

表达式示例: new Date()生成新的 Date 对象,没有任何副作用。 [1,2,3]产生一个没有任何副作用的新数组。 5+6产生一个新值 11.它只是产生新值,没有任何副作用。

语句产生一些行为或做一些事情,它也有一些副作用。根据副作用,可以对语句进行分类。

x=5; 是一个语句,这里的副作用是 x 中的赋值或更改。

setTimeout() - 计时器的启动是副作用。

语句通常用分号分隔。

表达式语句是具有某些副作用的表达式或简称为“具有副作用的表达式”。

表达式语句示例:

x+=6; 是复杂的表达式(主要表达式组)正在执行赋值,这是一个副作用,所谓的表达式语句。

delete a[2];
x=5;是一个“表达式语句”。x=5(不带分号)是一个表达式。是否产生行为或完成某事不是定义标准 - 有关更多信息,请参阅我的答案。
2021-05-02 12:22:47
setTimeout() 一个表达式。它甚至会产生value。delete a[5]也是一种表达。“表达产生或评估一些value。” — 你会考虑new Array(-1), JSON.parse("x"),(function(){"use strict"; x = 2;})()() => {await 3;}表达式吗?他们都抛出错误。
2021-05-21 12:22:47

表达式:解析为值的代码单元,如实例、文字运算符表达式示例:

> 3
> 1 + 2
> "expression"
> fn()
> []
> {}


语句:表示一条或多条指令的代码单元,通常以语言保留关键字开头,并以语句终止符显式隐式结束。语句示例:

> 3;
> let x = 3;
> if () {}
> for () {}
> while () {}