1

In the Mac (OS X 10.13.3) terminal, when I enter the REPL for node (v8.10.0) and enter the following various lines I get the indicated outputs:

> let a = 'abc'
undefined

> const b = 'abc'
undefined

> var c = 'abc'
undefined

> d = 'abc'
'abc'

Why the difference in output between the first three versus the last one?

I understand that, in ES5 non-strict mode, var x = 1 and x = 1 result in different variable scopes, but I suspect that's not the issue here.

I also understand that d = 'abc' is no longer a best practice for JavaScript and is not even allowed in, say, ES5 strict mode. However, I'm just trying to understand either the syntactic differences between the lines and/or how the node REPL interprets input. Does this have something to do with statements versus expressions (or definitions or assignments or declarations or...)?

(I've tried to search StackOverflow, but haven't found the answer in questions entitled 'node.js displays “undefined” on the console' or 'node.js REPL “undefined” '. I also can't find an answer in the Node.js v8.10.0 Documentation section for REPL. Searching Google for, say, node repl "return value", etc. also does not help.)

Andrew Willems
  • 11,880
  • 10
  • 53
  • 70
  • Maybe [this](https://stackoverflow.com/q/35389977/1048572) helps? – Bergi Mar 24 '18 at 22:47
  • Also [here](https://stackoverflow.com/a/43159103/1048572) and [there](https://stackoverflow.com/q/30662677/1048572) – Bergi Mar 24 '18 at 22:52

1 Answers1

2

tl;dr

The first two (let and const) are LexicalDeclarations. The next (var) is a VariableStatement. The last is an AssignmentExpression.

LexicalDeclarations and VariableStatements have no return value. AssignmentExpressions have. Details below.


Details

Beginning with the third, take the var identifier = expression, for instance. It is a VariableStatement. Its evaluation semantics are expressed in the spec as below:

Semantics

The production VariableStatement : var VariableDeclarationList ; is evaluated as follows:

  1. Evaluate VariableDeclarationList.
  2. Return (normal, empty, empty).

Notice the emptys in the return of the expression. The same doesn't happen in assignments (see the Return part).

About the let and const declarations, about their evaluation:

13.3.1.4 Runtime Semantics: Evaluation

LexicalDeclaration : LetOrConst BindingList ;

  1. Let next be the result of evaluating BindingList.
  2. ReturnIfAbrupt(next).
  3. Return NormalCompletion(empty).

Again, empty (undefined) return on normal completion. (Abrupt happens when the variable has already been declared, for example.)


The last one is an AssignmentExpression. It evaluates to (returns) a value. For instance, take its simplest form, Simple Assignment, evaluation specs:

The production AssignmentExpression : LeftHandSideExpression = AssignmentExpression is evaluated as follows:

    1. Let lref be the result of evaluating LeftHandSideExpression.
      ...
    1. Return rval.

Notice the returning of a value.

acdcjunior
  • 132,397
  • 37
  • 331
  • 304
  • In fact statements *do* have result values, which are usually printed on the console - but variable declarations indeed have an `undefined` result. – Bergi Mar 24 '18 at 22:45
  • This doesn't explain why `for (let i=0; i<1; i++) "hello";` *does* print something on the console - it's still a statement. – Bergi Mar 24 '18 at 22:53
  • 1
    Well, yeah, other statements such as [ExpressionStatement](https://www.ecma-international.org/ecma-262/5.1/#sec-12.4), `if`, `while` do have a return value. But `VariableDeclarationList`s don't. (To be exact, they return `undefined` as we all know.) – acdcjunior Mar 24 '18 at 22:53
  • 1
    @Bergi I have replaced the terms I used with more specific terms, from the spec. Don't know how much I killed the readability of the answer, but at least I hope it is less ambiguous now... – acdcjunior Mar 24 '18 at 23:23
  • Thanks for the effort/expertise. Your tl;dr is very helpful. While the spec info is a bit over my head, I can see that the `var` VariableStatement and the `let`/`const` LexicalDeclarations each return something that contains `empty` (presumably leading to the `undefined`) while the AssignmentExpression returns a non-`empty` value, specifically `rval` (from `GetValue(rref)`...just to show you I attempted to follow the links!). Is the following correct: `x = 1` is an assignment expression, is also a statement (in the same way that `42` is) but is not a declaration? – Andrew Willems Mar 25 '18 at 00:04
  • Yes, that is correct. `x = 1` is an [AssignmentExpression](https://www.ecma-international.org/ecma-262/5.1/#sec-11.13) (it matches *LeftHandSideExpression = AssignmentExpression*) and, as an Expression (find it down in the [Expressions](https://www.ecma-international.org/ecma-262/5.1/#sec-A.3) list) it can also be used as a [statement](https://www.ecma-international.org/ecma-262/5.1/#sec-12), more specifically, a [ExpressionStatement](https://www.ecma-international.org/ecma-262/5.1/#sec-12.4). – acdcjunior Mar 25 '18 at 00:18
  • ...but it is _not_ a declaration? – Andrew Willems Mar 25 '18 at 00:44
  • I don't think so... See, a [Program](https://www.ecma-international.org/ecma-262/5.1/#sec-14) is roughly a sequence of function declarations or statements. And in the [list of what a Statement is](https://www.ecma-international.org/ecma-262/5.1/#sec-A.4) there's no *VariableDeclaration*. It only appears in the context of *VariableStatement* (which is a "`var` *VariableDeclarationList*", where a *VariableDeclarationList* is a list of *VariableDeclaration*). – acdcjunior Mar 25 '18 at 01:05
  • So, considering 2 programs: `something; var x = 1; other;` and `something; x = 1; other;`. In the first, `x = 1` is a [VariableDeclaration](https://www.ecma-international.org/ecma-262/5.1/#sec-12.2), in the second it is an [ExpressionStatement](https://www.ecma-international.org/ecma-262/5.1/#sec-12.4)(an [AssignmentExpression](https://www.ecma-international.org/ecma-262/5.1/#sec-11.13)). If you paste the [JavaScript gramar](https://raw.githubusercontent.com/pegjs/pegjs/master/examples/javascript.pegjs) in https://pegjs.org/online and write `x = 1`in the input box you'll get a similar result. – acdcjunior Mar 25 '18 at 01:20