3

Why next code doesn't occur errors?

var bar = 1,
    foo = {};

foo: {
    bar: 2;
    baz: ++bar;
};

It returns 2

It known that javascript has labels, it helps to manage loops and if-statements. Could this code be useful? I saw that AngularJS framework with :: operator provide one-time binding. Maybe do you hear some another example of using that strange operator.

Venkata Krishna
  • 1,768
  • 2
  • 14
  • 21
Oleksii
  • 328
  • 3
  • 17
  • See this question: [What does colon do in Javascript?](http://stackoverflow.com/questions/418799/what-does-colon-do-in-javascript) – doldt Apr 20 '15 at 08:38
  • 1
    @doldt: That's a similar-looking but entirely different use of colons. – user2357112 Apr 20 '15 at 08:39
  • `foo: { bar: 2; baz: ++bar; };` must be `foo: { bar: 2, baz: ++bar };` you're using `;` instead of `,` – mohamedrias Apr 20 '15 at 08:41
  • @mohamedrias: No, the code is correct as given. That's not an object literal; it's a block statement with labels inside that just looks a lot like an object literal. – user2357112 Apr 20 '15 at 08:42
  • @user2357112 The answers in that link explain the label use-case of colons, which is in effect here. – doldt Apr 20 '15 at 08:45

1 Answers1

6

It's not an error because the foo in foo: {...} is a statement label. It has nothing to do with your foo variable, and it has nothing to do with assigning anything to anything.

Similarly, the { and } define a block, not an object, and the bar and baz inside are also statement labels.

The statements

2;

and

++bar;

are perfectly valid. The first looks a bit odd, but it's valid; in JavaScript, any expression can be used as a statement, including a simple constant. (Which is useful; it's how JavaScript slipped in the "use strict" directive.)

The result is 2 because the block takes the value of the last statement in the block, which is ++bar;.

Unless something is using those statement labels, that code is equivalent to:

var bar = 1,
    foo = {};

2;
++bar;

Could this code be useful?

Purely as given, I don't see how, no. But note that if you had a loop inside the foo block, and you had something after the loop, you could use a directed break to jump past the thing after the loop:

var bar = 1,
  foo = {};

foo: {
  bar: 2;
  baz: ++bar;
  for (var n = 0; n < 10; ++n) {
    snippet.log("n = " + n);
    if (Math.random() < 0.3) {
      break foo;
    }
  }
  snippet.log("Probably don't get here");
};
snippet.log("Done");
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

There, you won't see Probably don't get here except in the outlying case where Math.random() returned a value less than 0.3 ten times in a row.

You need a loop or a switch in order to do that, though; break is only valid in loops and switch. And it would be a very unusual thing to do...

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 4
    And the `++bar;` evaluates to 2, which is then what the containing block `{ }` evaluates to, (i.e. it's last statement.), which is why it returns `2`. – Sam Hasler Apr 20 '15 at 08:45
  • 1
    @SamHasler: Thanks! I'd missed that part of the question, and I didn't know that about blocks until I went and looked it up. :-) – T.J. Crowder Apr 20 '15 at 08:49