1

I tried the following code in the Google Chrome console and I’m getting this output. Why is there an additional 4 printed?

var i = 0;

do{
  console.log(i);
  i++;
} while(i < 5);

Output:

0
1
2
3
4
4
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
nandu kk
  • 368
  • 1
  • 10
  • 2
    There isn't an extra 4 – Taplar Jun 22 '18 at 17:45
  • 1
    that's return value, which you are mistaking for console.log. try `var i=0;do{console.log('i = ', i);i++;}while(i<5);`, you will figure it out – kiddorails Jun 22 '18 at 17:46
  • Run the snippet. There is nothing extra. You might just have an extra `console.log()` somewhere. – Alex Jun 22 '18 at 17:46
  • So there is an extra one when you write it in the console directly and run it? – epascarello Jun 22 '18 at 17:46
  • It's just chrome console, print result of statement at last – Hikmat G. Jun 22 '18 at 17:46
  • You're seeing the result of the statement chain. – Fissure King Jun 22 '18 at 17:46
  • @Alex If you paste his snippet into the Javascript console you'll see the extra 4 – Barmar Jun 22 '18 at 17:46
  • @Barmar I'll try now – Alex Jun 22 '18 at 17:47
  • Ran in JSFiddle, nothing extra. – Alex Jun 22 '18 at 17:47
  • @Alex he is doing in chrome js console. try his snippet, you will understand the confusion – kiddorails Jun 22 '18 at 17:48
  • @Alex It only happens in the console. It's the console printing the value of the statement after it's done. – Barmar Jun 22 '18 at 17:48
  • You should always test your logic in a fiddle or on an actual page. That reflects 100% what will happen, and what you care about happening, in the real code. – Taplar Jun 22 '18 at 17:48
  • The "result" of the `do{...} while(i<5);` loop is the "result" of the last statement in the loop body (`i++;`). Usually these are ignored but not by (Chrome's) console. – Felix Kling Jun 22 '18 at 17:48
  • I just did it in console. Had a brainfart moment just there. – Alex Jun 22 '18 at 17:48
  • So incrementing i will cause chrome to pick up the return in the end? – Alex Jun 22 '18 at 17:49
  • `var i=0;do{i++;}while(i<5);` just run that – epascarello Jun 22 '18 at 17:51
  • @Alex: No, it just the result of the last statement in the loop body. – Felix Kling Jun 22 '18 at 17:51
  • Yes. If you do `x = 4;` in your console, you will see it print 4. You didn't console log that. It's just the browser returning the result of it's last expression. – Taplar Jun 22 '18 at 17:51
  • Ahh okay. Makes sense now. – Alex Jun 22 '18 at 17:52
  • 1
    @Taplar: It prints `undefined`, at least in Chrome. – Felix Kling Jun 22 '18 at 17:52
  • I get 4 in chrome. Or I thought I did. wtf... @FelixKling – Taplar Jun 22 '18 at 17:52
  • 2
    Notice also that Chrome's console puts a tiny "<-" arrow next to the last `4`. This indicates the return value. – ggorlen Jun 22 '18 at 17:53
  • Ok `var x = 4;` is undefined `x = 4` is 4 – Taplar Jun 22 '18 at 17:53
  • 2
    Here is another example: `if (true) { 5 }`. The Chrome console shows the value of the [completion record](https://www.ecma-international.org/ecma-262/8.0/index.html#sec-completion-record-specification-type) of the statement, that's all. – Felix Kling Jun 22 '18 at 17:54
  • `var` statements cannot be an rvalue, that's why its "return value" (according to the console, and for lack of a better word) is `undefined` and not `4` – Patrick Roberts Jun 22 '18 at 17:56
  • @Alex and others: Please consider cleaning up this comment thread. – Sebastian Simon Jun 22 '18 at 18:05
  • @Xufox: Good find. I felt there must be a duplicate but didn't find it. – Felix Kling Jun 22 '18 at 18:14
  • 1
    @PatrickRoberts: That's not right. `if` statements cannot be rvalues either and yet they have a "return value". The value of the a completion record of a variable declaration is explicitly set to empty: http://ecma-international.org/ecma-262/8.0/index.html#sec-variable-statement-runtime-semantics-evaluation – Felix Kling Jun 22 '18 at 18:18
  • @FelixKling If I understand correctly, a completion record with [[Value]]: empty is not differentiable from [[Value]]: undefined when inspecting the value at runtime. Since both of them will evaluate to `undefined`, I fail to see why that's even relevant. – Patrick Roberts Jun 22 '18 at 18:32
  • @PatrickRoberts: Where did you see `[[Value]]: undefined` ? The completion record of an `if` statement is not always `[[Value]]: undefined` if that's what you are implying. Otherwise I don't understand your comment. – Felix Kling Jun 22 '18 at 18:35
  • @FelixKling I was not implying anything about if statements. My original assertion was that `var` statements have a return value of `undefined` while you "corrected" that assertion by saying it was actually [[Value]]: empty, which evaluates to `undefined` anyway. – Patrick Roberts Jun 22 '18 at 18:36
  • 1
    @PatrickRoberts: Ah got it. That was not my point (don't care about `empty` vs `undefined`). I understood your comment that you were implying that `var` statements result in `[[Value]]: undefined` *because* they cannot be rvalues. And I just wanted to clarify that this is not reason (because there are other non-rvalue constructs that result in `[[Value]]: whatever`. Sorry for the misunderstanding. – Felix Kling Jun 22 '18 at 18:39
  • @FelixKling OH that makes sense. Thanks for the clarification, and sorry for the misunderstanding as well – Patrick Roberts Jun 22 '18 at 18:40

3 Answers3

5

There is no extra 4 at end. Your loop is correct and works just fine :). That's return value of the i++ expression, which you are mistaking for console.log in developer console. Try this, you will figure it out;

var i=0;do{console.log('i = ', i);i++;}while(i<5);

Edit Thanks to @ggorlen for pointing this out, it's the return value of last expression in block({}) which is i++, i increments the value and returns it's last value (if i = 4; i++ returns 4 and makes value of i = 5), (++i, returns 5 and makes value of i = 5)

var i=0;do{console.log('i = ', i);++i;}while(i<5);

will give return value of 5

kiddorails
  • 12,961
  • 2
  • 32
  • 41
  • I would say: `var i=0;do{console.log(i);i++;}while(i<5);` returns `4` and that is the last one :) –  Jun 22 '18 at 17:50
  • Specifically, it's the return value of the `i++` statement, to be clear. Try it in the console: `var i = 0; i++;` output will be `0` and the value stored in `i` will be 1. – ggorlen Jun 22 '18 at 17:51
  • Vouching with @Andrew – Alex Jun 22 '18 at 17:51
  • Hi, can you also say what you mean by return value. – nandu kk Jun 22 '18 at 17:51
  • @nandukk expression often have a value when an expression execution ends. like `true` is an expression with return value of `true`. (3 && 4) is an expression with a return value of 4. The return value are used in conjunction to create powerful logic. Read more about it in your js journey :) – kiddorails Jun 22 '18 at 17:52
  • @ggorlen Thanks for that hat-tip. I edited my answer to reflect that :+1: – kiddorails Jun 22 '18 at 17:55
2

JavaScript has the concept of "Completion Records". Basically every statement produces a completion record.

The Completion type is a Record used to explain the runtime propagation of values and control flow such as the behaviour of statements (break, continue, return and throw) that perform nonlocal transfers of control.

You usually cannot do anything with these in user land code, but the runtime needs those to properly execute your program. However the Chrome console will print the value of the completion record of the last statement it executes.

Without going into to much details, here is what happens:


The simplest example to demonstrate this behavior is simply

42;

The result of evaluating this expression statement is a completion record that looks something like

{
  type: normal,
  value: 42,
  target: empty
}

You will see it print 42 in the console because that's the value of the completion record of the expression statement.

A slightly more evolved example:

if (true) {
  42;
}

will print the same.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • Because `42` returns `42`, that's why we get `42`, lmao :) –  Jun 22 '18 at 18:09
  • @Andrew: Extended it a bit so that the point becomes clearer. – Felix Kling Jun 22 '18 at 18:12
  • Can I *quick* understand your answer like this: `console.log(do{...}while(...))` prints `4`? –  Jun 22 '18 at 18:22
  • 1
    @Andrew: Not quite, because that's not syntactically valid. But if there was a magically equivalent to `console.log` that prints completion records then `printCompletion do{...}while(...)` would print `{type: normal, value: 4, target: emtpy}`. Chrome pulls out the `value` of that and prints it. – Felix Kling Jun 22 '18 at 18:23
0

Yeah, it's normal that extra 4. It's called expression evaluation. Id doesn't mean it's printing, but instead evaluating i to you.

Check here to know more about it.

This is just chrome helping you to know the dynamic environment of your variables.

inafalcao
  • 1,415
  • 1
  • 11
  • 25