4

I think that i should ask new question about jSHint, discussion started here, i can see now strange warning from JSHint, i just want to know why.

This services was suggested.

So i have this code in JSHint:

var foo = function() {
   return {
       hi: console.log("foo")
   } //line 15 <------ why we have to put ; here?
};

var foo1 = function() {
    return // i know about ; here, please read post
    {
        hi: console.log("foo1")
    }; // line 22 <---- why we don't need to put ; here?
};

I marked lines where i am getting warning via comment "this line" above.

So, question:

I have 2 strange warnings:

First warning 15 Missing semicolon. about 15 line

Second warning 22 Unnecessary semicolon. about 22 line

But those 2 lines looks for me identical, what am i missing? why we have 2 different warnings here?

EDIT

Question is not about behavior, question is about warnings. Why are they different?

I know that i missed semicolon in second return!

Community
  • 1
  • 1
alexey
  • 1,381
  • 9
  • 19

3 Answers3

2

Your first example runs in the way you would expect. The function will return an object with the hi property. The return statement includes an optional expression and must be terminated by a semicolon (either explicit or implicit via automatic semicolon insertion). JSHint by default prefers explicit semicolons and therefore points out that you've missed one.

Your second example does not run in the way you may expect. The function will return undefined. The reason for this is that the parser believes the return statement is not followed by an expression. This is because the grammar is somewhat ambiguous to allow for automatic semicolon insertion. This example is parsed as an empty return statement followed by a block. Blocks do not need to be terminated by a semicolon, hence JSHint points out that the semicolon used in your second example is unnecessary.

James Allardice
  • 164,175
  • 21
  • 332
  • 312
  • The question is: Why there is no error _missing semicolon in line 19?_ That's a return statement and there is no semecolon. So why there is no error message either? – Qwertiy Mar 14 '16 at 12:58
  • @Qwertiy - Ah, I see. If I paste the code in question into http://jshint.com I do receive a "missing semicolon" error for that line (as well as a "line breaking error"). – James Allardice Mar 14 '16 at 13:00
  • about we 19 line another error: 'Line breaking error 'return', don;t know why, but ok. My question is: what is the difference between ' optional expression' and 'block'? – alexey Mar 14 '16 at 13:01
  • 2
    @alexey - A [block](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/block) is a statement in its own right. You can use `{ /* ... */ }` anywhere a statement is allowed. The same syntax is used for defining object literals. The ECMAScript grammar has to allow for both use cases. In your first example `{` is parsed as the start of an object literal. In the second it's parsed as the start of a block because there was a line break and no explicit semicolon after the `return`. – James Allardice Mar 14 '16 at 13:04
2

Semicolons should follow statements. They do not need to follow blocks. For example, here's an unnecessary semicolon with if:

if(foo === bar) {
    //...
};

The semicolon after the if block is never necessary.

What does this have to do with your case? Well, sometimes { ... } is a block, and sometimes { ... } is an object literal. The surrounding context lets the grammar determine which it is. In your first case, it's a an object; in the second case, it's a block.

The characters following a return statement on the same line are parsed as an expression. When { ... } is parsed as an expression, it is an object literal. In your first example, return { ... } is a return statement with an object expression. It should have a terminating semicolon, because it is a statement.

The critical thing to understand here is that the ECMAScript grammar doesn't allow a line break to separate return and its return-value expression. It's in ES2015 §11.9.1, Rules of Automatic Semicolon Insertion:

ReturnStatement[Yield] :

  • return [no LineTerminator here] Expression ;
  • return [no LineTerminator here] Expression[In, ?Yield] ;

A ReturnStatement can't have a LineTerminator character between the return and the Expression.

Since you do have a newline character between your return and the { ... }, the { ... } part is not parsed as belonging to the return. It is standalone, which means it is a parsed as a block. The { ... } sequence can only be parsed as an object when it is part of a larger statement or expression, like

  • assignment, foo = { ... }
  • function argument (bar({ ... })
  • a return value (return { ... })
  • etc.

When { ... } is purely on a line by itself, it is treated as a block.

Since the second case has a block, not an object, it does not need a semicolon, as described at the beginning of this answer.

Community
  • 1
  • 1
apsillers
  • 112,806
  • 17
  • 235
  • 239
  • if we put ; after second return, we will see this warning: Label 'hi' on console statement. , what this means? – alexey Mar 14 '16 at 13:29
  • @alexey Since `{...}` here is a blcok, the `hi:` in `{ hi: ... }` is a [label](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label): http://stackoverflow.com/q/31924988/710446. JSHint is probably just warning you that you're using a label in an meaningless context -- labels are only useful when used before loop constructs like `while`. – apsillers Mar 14 '16 at 13:32
  • thank you very much! now i think i have much better understanding :) – alexey Mar 14 '16 at 13:33
  • 1
    @alexey Just confirmed: if you do `hi: while(true) { }`, the warning goes away. – apsillers Mar 14 '16 at 13:34
0

2 things, firstly here

return {
       hi: console.log("foo")
   } 

you need ; to specify end of object literal and here

 return
    {
        hi: console.log("foo1")
    };

because you didn't put { after return, a ; it is put there for you by js engine (optional semicolon).

Ramanlfc
  • 8,283
  • 1
  • 18
  • 24
  • why we don't have put semicolon in second return? why we have to put semicolon in first return? – alexey Mar 14 '16 at 12:52
  • 1
    @alexey the first case is read by js engine as a object literal , while in the 2nd case it finds `return` and nothing after it on that line , so it add `;` and thus your 2nd case ends up being a code block – Ramanlfc Mar 14 '16 at 12:58