Brendan Eich recently repeated that he regrets not having given JavaScript significant newlines. This post explains what that would be like. Quote:
... my only regret with ASI [automatic semicolon insertion, making them optional] was that I didn't use significant newlines throughout the grammar, but without requiring \ continuations for expressions spanning multiple lines where an operator ends the non-final lines.
Example:
"abc" .lengthThis is interpreted as:
"abc".lengthThe following are examples where you would expect a semicolon to be inserted, but it isn’t.
a = b + c (d + e).print()One of the intermediate evaluation steps is the function call c(d + e)
var foo = "bar" [ "red", "green" ].foreach(function(c) { console.log(c) })Evaluates, among other things, the expression "bar"[ "red", "green" ]. The expression inside the square brackets is the binary comma operator applied to the operands "red" and "green". That operator evaluates both operands and returns the value of the second one. Hence, the original expression is equivalent to "bar"["green"] – the value of the property green of the string "bar".
a = b /hi/g.exec(c).map(d)The above is interpreted as:
a = b / hi / g.exec(c).map(d);
You would still delimit blocks with curly braces (as opposed to indentation being significant, like in Python or Haskell). But the default for a newline would be to terminate a statement. You may continue in the following line if there is a trailing (binary) operator (which includes dot and comma) or if there are unclosed parentheses, square brackets or curly braces.
return a + b return (a + b) obj.foo(arg1, arg2)The net result is that optional semicolons are safer and more intuitive. If you want to put multiple statements in a single line, you obviously still need them:
obj.m1(); obj.m2()Significant newlines in current JavaScript. Some statements such as return already have significant newlines: If you add a newline after the return keyword, it terminates the statement. Example:
return { first: "Jane" } // interpreted as return; { first: "Jane" }The second of the two lines is interpreted as a block with the expression statement "Jane", prefixed by the label first.