This question already has answers here:
Do you recommend using semicolons after every statement in JavaScript?
(11 answers)
Closed 7 years ago.
I want to know, is this legal?
function test()
{
alert ("hello")
$("#loading").show();
}
Or should I write this instead:
function test()
{
alert ("hello");
$("#loading").show();
}
Are semicolons optional in JavaScript? Because I saw this in a forum:
No, semicolons are usually optional in JavaScript (Google for ASI / automatic semicolon insertion). Using them makes the code look much cleaner though and ASI is a horrible mis-feature (at least in my opinion).
Semicolons are not always mandatory, but I would always recommend using them. See the ECMAScript spec for the rules on automatic semicolon insertion:
Certain ECMAScript statements (empty statement, variable statement,
expression statement, do-while statement, continue statement, break
statement, return statement, and throw statement) must be terminated
with semicolons. Such semicolons may always appear explicitly in the
source text. For convenience, however, such semicolons may be omitted
from the source text in certain situations. These situations are
described by saying that semicolons are automatically inserted into
the source code token stream in those situations.
Update (to explain further)
Perhaps the most common situation used to show why automatic semicolon insertion can be bad is that touched on by #sissonb in another answer. Consider the following:
function something(a, b) {
return
a + b;
}
What you may be expecting is for the new-line to be ignored, and the code interpreted as:
function something(a, b) {
return a + b;
}
Unfortunately, automatic semicolon insertion comes into play, and the code is actually interpreted like this:
function something(a, b) {
return;
a + b;
}
And an empty return statement means the function returns undefined. So instead of a nice sum of the two argument, you get undefined and potentially end up very confused as to where you've gone wrong! Which is why I completely agree with the statement in your question that automatic semicolon insertion is a horrible misfeature.
Example (returns undefined because of ASI).
Example (returns expected result).
Semicolons are not mandatory. They are automatically added at the end of a line if it is missing which actually causes this code to return undefined.
return
{
text:"hello"
}
Related
why this kind of bad design is made on js? Is there any special reason to design the automatic semicolon insertion like this?
Here is my code, It is not work in js in chrome:
(function(){console.log("abc");})()
(function(){console.log("123");})();
Here is the error:
Uncaught TypeError: (intermediate value)(...) is not a function
I know the right version of this code is :
(function(){console.log("abc");})();
(function(){console.log("123");})();
I just want to know why js syntax is designed so stupid. History reason?
I also add this question as a warning to everybody try to use the automatic semicolon insertion of javascript, please just add ; everywhere it needs, the automatic semicolon insertion of javascript is rubbish. It does not work as your expect.
The exist answer is too complex to my case, so I ask a new one:
https://stackoverflow.com/a/2846298/1586797
Another looks good but not work case 2:
x=1
(function(){console.log("123");})()
The linked question's answers explain the spec's three rules for ASI, for example this one. tl;dr:
If it doesn't work, try with semicolon.
The program should end with a semicolon.
If a statement says "can't put newline here", punish it with semicolon.
Your code does not satisfy any of the criteria.
The first line could return a function, and if so that function should be allowed to be invoked; so ( that the second line begins with is not illegal
The first line is not the last line of the program
There is no restricted syntax here.
Therefore, no automatic semicolon for you.
Some people have thus claimed that while (f(){})() syntax is good IIFE syntax, it might be good to do !f(){}() instead:
!function(){console.log("abc");}()
!function(){console.log("123");}();
This works as intended because ! just negates the (discarded) result of the function application, and also because ! as purely unary operator is an illegal character to continue the first line (i.e. f(){}()! is not a thing). This triggers rule 1, and ASI can take place.
The counterargument is that it is butt-ugly (i.e. for anyone not already familiar with the practice, it takes a while for them to understand the purpose of ! in this idiom).
Your second example is similar in nature: as far as the JS parser is concerned, 1 is a value (the fact that it is an integer and could not possibly be a function is a bit lost to it). Look at this example that syntactically is completely equivalent to yours:
a=function(f) { console.log("A CALLED!"); return f; }
x=a
(function(){console.log("123");})()
# => A CALLED!
123
Here, a is a function, so it can be invoked with function(){console.log("123");} as an argument; it returns function(){console.log("123");} unchanged after printing to the console; then () invokes that return value, and 123 is printed as well. Everything works. Thus, Rule #1 is not triggered, no semicolon for you.
(function(){console.log("abc");})()
(function(){console.log("123");})();
is equivalent to:
(function(){console.log("abc");})()(function(){console.log("123");})();
And is what is usually referred to as function currying.
For IIFEs (immediately invoked function expressions) you need to end with ;
For more on function currying see this post. Obviously your console log functions do not work as currying functions, but the syntax yourFunction(a)(b)(c) is a cool feature of the language that is used for currying.
Your code can be simplified as:
(function(){})()()();
This code will get same error.
The () expect a expression to call.
The first () call the (function(){}), the second () call the (function(){})()'s result, but the result is not a function, so it's wrong.
Without the semicolon those statements are chained. You call the first function and give the second func as argument to the return value of the first one. This could actually work, if the first function had a function as return value.
When you expand the code it becomes more obvious:
var a = function(){console.log("abc");};
var b = function(){console.log("123");}
(a)()
(b)();
the last two lines become:
(a)()(b)();
this is equivalent to
var x = a();
x(b);
since a does not return anything, it cannot call it as function with b as argument.
I think this will be clearer if you use this:
x=1
(function(){console.log("123");})()
The error states 1 is not a function. Makes it clear that (function...) is treated like the argument of a function call to 1:
x=1(function(){console.log("123");})()
Because ()() is self-invoking function and ();() are two differnt functions and interpreter is interpreting it accordingly.
Here two pieces of code are totally different for an interpreter.
(function(){console.log("abc");})()(function(){console.log("123");})();
and
(function(){console.log("abc");})();(function(){console.log("123");})();
however, this code will work fine
var a=12
var b=10
console.log(a+b)
Long answer sort :
(function(){console.log("abc");})()
is trying to immediately-invoke the preceding expression which is
(function(){console.log("123");})();
Which would be the return value of the preceding IIFE.
IIFEs can act differently in the missing semicolon situation. That is why we see code as follows:
;(function() {
console.log('abc');
})()
Please have a look of details description here : https://gist.github.com/khellang/8518964
I was reading the answer to this question (about the "wat" video) and it said:
{}+[]
This is interpreted as an empty block of code, unary plus and empty array. First part does nothing, array is converted to a comma-separated string of it's elements (empty string for empty array), then to a number (empty string is converted to 0), hence 0.
I am currently learning JS from "The Definitive Guide" so I try to really understand things like that.
My question is, when does JS decide to interpret {} as an empty block of code, instead of an empty object?
Also, there are some inconsistencies between Node.js and Firebug which I would like to understand.
Firebug:
Node.js:
Let's look at the language grammar, shall we? Section 12, Statements:
Statement :
Block
VariableStatement
EmptyStatement
ExpressionStatement
...lots of other stuff...
That's a very fancy way of saying that a statement can be a block, a variable statement, an empty statement, an expression statement, or lots of other stuff. Notice that the first option there is a 'Block':
Block :
{ StatementList(opt) }
StatementList :
Statement
StatementList Statement
Which is again, a fancy way of saying that a block is a {, optionally followed by a bunch of statements, followed by a }.
And that's what you see in your example: Before the JavaScript parser thinks that what you have could be an object literal (which is defined somewhere under ExpressionStatement, the 4th thing a 'Statement' could be), it first thinks that you have a 'Block'.
Edit: If you want, you can see it live in a JavaScript engine's source code:
In V8, Chrome's JavaScript engine, we go into Parser::ParseStatement. The first thing it checks is whether we're on a {, and if it does, parses as block.
In SpiderMonkey, Firefox's JavaScript engine, we go from Parser::statement to again see the first check being against a { and parsing it as a block statement.
Regarding your second question, that's been covered to great detail on this question. To summarise in a sentence: Node.js treats your input as if it were an expression (thus it can't be a 'Block'), while Firebug/Chrome dev tools treat it like a 'Statement'.
When the first token in a new statement is {, then {} is interpreted as an empty block.
(Actually of course when { appears after the header clause of something like if or while, then {} is an empty block too, but that's not the interesting case.)
Thus in any other context, like say an argument to a function:
foo({});
the {} is interpreted as an empty object literal.
This situation is similar to the way in which the function keyword is treated differently when it's the first thing in a statement. The syntax has ambiguity, and the parser solves the problem with fixed rules.
This question already has answers here:
Why do results vary based on curly brace placement?
(6 answers)
Closed 6 years ago.
I am quite new to JavaScript and just started some more serious development in JavaScript. I had a lot of fun implementing the Module pattern. One thing that really drove me crazy was the behavior of the 'return' statement. It is a big difference if you write
Test = ( function()
{
var message = "Hello World!";
return
{
// Does not work
printTest: function() { window.alert(message); }
};
}());
or
Test = ( function()
{
var message = "Hello World!";
return {
// Works well
printTest: function() { window.alert(message); }
};
}());
Note the curly brace after the 'return' statement.
Is that a typical stupid rookie error and is well documented somewhere?
Firebug was not able to give a hint. IE9 and Chrome did report some obscure syntax error at a later location in the code: the opening brace after the 'function' statement in "printTest: function()".
Any comments on this? Are there more such pitfalls in JavaScript?
If you put your brackets to the next line, the interpreter assumes that there is a semi-colon.
So your return statement will be interpreted as:
return;
{
printTest: function() { window.alert(message); };
}
If I remember well, i've red about this problem in JavaScript: The Good Parts
A.3. Semicolon Insertion
JavaScript has a mechanism that tries to correct faulty programs by automatically inserting semicolons. Do
not depend on this. It can mask more serious errors.
It sometimes inserts semicolons in places where they are not welcome. Consider the consequences of
semicolon insertion on the return statement. If a return statement returns a value, that value expression
must begin on the same line as the return:
return
{
status: true
};
This appears to return an object containing a status member. Unfortunately, semicolon insertion turns it
into a statement that returns undefined. There is no warning that semicolon insertion caused the
misinterpretation of the program. The problem can be avoided if the { is placed at the end of the previous line
and not at the beginning of the next line:
return {
status: true
};
"JavaScript: The Good Parts by Douglas Crockford. Copyright 2008 Yahoo! Inc.,
978-0-596-51774-8."
Are there more such pitfalls in JavaScript?
This made me smile :) Oh boy, you're in for a treat.
Have a look at this site for example: http://wtfjs.com/
Yes, it's a difference. I think it actaully is a part of documentation, the subject that is to be returned has to be in the same line as the return statement.
It's beacause semicolons are optional, and the expression is interpreted as
return;
{
....
}
JavaScript does automatic semi-colon insertion. If you put the brackets on the next line after the return, the interpreter automatically inserts a semi-colon after the return, ending the statement.
I have seen and used javascript code that both has and omits the ';' from the end of statements. Are they required in some cases and not in others? If so can you give some examples, and if not what is the general standard, to use the ';' or to not...that..is the question??
JavaScript uses a (generally disliked) method called Semicolon Insertion, where it will allow you to omit semicolons.
The rules for where you can and cannot insert semicolons is extensive, and covered fairly well here.
In general, do not rely on semicolon insertion. It is a poorly thought out feature and will hurt you before it helps you.
Not only should you always use semicolons, but you should also get in the habit of putting your { braces on the same line, as semicolon insertion can actually misinterpret what you meant.
For example, say I'm trying to return a javascript object from a function:
function f() {
return { "a":"b", "c":"d" } // works fine
}
function g() {
return // wrong!!!
{
"a":"b",
"c":"d"
}
}
If I put the { on a new line (as I did in g), the return statement will actually have a semicolon inserted after it, destroying the meaning of what you were saying.
Overall, semicolon insertion is a poor feature and you should never rely on it.
Use ; to mark the end of a statement. Javascript follows the syntactical theme set in C family languages, and ; is the delimiter for the end of a statement.
What code have you seen that omits this?
If there's no more code in the block after a line, the ; is technically optional. You should include it anyway.
Always use the semicolon, this makes the code easier to read. Right now I am not aware of any situation where it can be omitted.
I remember there is a convention/recommendation to put opening brace in the same line, because of the way JavaScript adds a semicolon or something.
//OK
function blah(){
};
//Probably not OK
function blah()
{
};
But I don't find a relevant source to confirm/deny this.
Is this true? Or just a myth?
The issue you are thinking of is for return statements.
return {
value: 'test'
}
Works fine, but the following does not:
return
{
value: 'test'
}
JavaScript adds a semicolon after return turning the above into:
return;
{
value: 'test'
}
This post on Elegant Code gives some explanation of automatic semicolon insertion, but in regard to returning objects, not declaring functions.
Douglas Crockford gives a reason for choosing the K&R style [1]:
"I always use the K&R style, putting the { at the end of a line instead of the front, because it avoids a horrible design blunder in JavaScript's return statement.
The blunder he is referring to is how JavaScript handles the return statement differently in the following two scenarios:
return {
'status': 'ok'
};
... and:
return
{
'status': 'ok'
};
The first one will return an object with a status property, while the latter will return undefined because of semicolon insertion."
[1] Douglas Crockford: JavaScript: The Good Parts: Style (p. 96)
The JavaScript Garden has a chapter about automatic semicolon insertion. It gives good examples when semicolons are added automatically:
JavaScript is not a semicolon-less
language, it in fact needs the
semicolons in order to understand the
source code. Therefore the JavaScript
parser automatically inserts them
whenever it encounters a parse error
due to a missing semicolon.
In your example JavaScript wouldn't encounter an error due to a missing semicolon though.
There is no issue with declaring functions, but you can get into trouble when returning objects:
function foo()
{ // this is OK
return
{ // this is BAD!
name: "bletch"
};
// actually returns undefined!
}
A semi-colon is automatically inserted after the return statement, and that will break your code.
It's a myth. function blah() is always required to be followed by a expression block, so makes no difference which style you use. The first style is simply the most widely used form.