This question already has answers here:
Do you recommend using semicolons after every statement in JavaScript?
(11 answers)
Closed 9 years ago.
Are there any reasons, apart from subjective visual perception and cases where you have multiple statements on the same line, to use semicolon at the end of statements in JavaScript?
It looks like that there's plenty of evidence suggesting that use of semicolons is highly optional and is required in only few of the specific cases.
Because JavaScript does nasty things to you when it guesses where to put semicolons. It's better to be explicit and let the interpreter know exactly what you meant than it is to let the idiot box guess on your behalf.
References:
http://www.webmasterworld.com/forum91/521.htm
http://www.howtocreate.co.uk/tutorials/javascript/semicolons
http://robertnyman.com/2008/10/16/beware-of-javascript-semicolon-insertion/
...and a cast of thousands.
It looks like there are very few reasons, or, actually, edge cases, when one would want to use semicolons.
http://aresemicolonsnecessaryinjavascript.com/ <- this is down now, use
https://github.com/aresemicolonsnecessaryinjavascript/aresemicolonsnecessaryinjavascript.github.com
If you asked, because you come from a Python background: The difference is:
in Python you shouldn't terminate lines with anything, but are allowed to use the semicolon, if you must
in JavaScript you should terminate the lines with a semicolon, but are allowed (PDF, page 26, point 7.9) to omit it, if it's unambiguous
Because
Debugging the subtle bugs that occur when you don't is a waste of time you could be spending doing something cool
It makes it clearer to someone maintaining the code later what you intend
Not all code maintainers understand the rules for automatic insertion well enough to maintain code with them left out
Leaving them out relies on all tools that process JavaScript code in your toolchain getting the rules exactly right (for instance, some minifiers/packers/compressors don't, including Crockford's jsmin, which will break code that relies on ASI in some places)
As Douglas Crockford suggests -
Put a ; (semicolon) at the end of every simple statement. Note that an assignment statement which is assigning a function literal or object literal is still an assignment statement and must end with a semicolon.
Related
I'm currently working on a small little dsl, not unlike rabl. I'm struggling with the implementation of one of my rules. Before we get to the problem, I'll explain a bit about my syntax/grammar.
In my little language you can define properties, object/array blocks, or custom blocks (these are all used to build a json object/array). A "custom block" can either be one that contains my standard expressions (property, object/array block, etc) or some JavaScript. These expressions are written as such -
-- An object block
object #model
-- A property node
property some, key(name="value")
-- A custom node
object custom_obj as
property some(name="key")
end
-- A custom script node
property full_name as (u)
// This is JavaScript
return u.first_name + ' ' + u.last_name;
end
end
The problem I'm running into is with my custom script node. I'm having a real hard defining the script token so that JISON can properly capture the stuff inside the block.
In my lexer, I currently have...
# script_param is basically a regex to match "(some_ident)"
{script_param} { this.begin('js'); return 'SCRIPT_PARAM'; }
<js>(.|\n|\r)*?"end" %{
this.popState();
yytext = yytext.substr(0, yyleng - 3).trim();
return 'SCRIPT';
%}
That SCRIPT token will basically match anything after (u) up to (and including) the end token (which usually ends a block). I really dislike this because my usual block terminator (end) is actually part of the script token, which feels totally hacky to me. Unfortunately, I'm not able to find a better way to capture ANYTHING between (..) and end.
I've tried writing a regex that captures anything that ends with a ";", but that poses problems when I have multiple script nodes in my dsl code. I've only been able to make this work by including the "end" keyword as part of my capture.
Here are the links to my grammar and lexer files.
I'd greatly appreciate any insight into solving my problem! If I didn't explain my problem clearly, let me know and I'll try my best to clarify!
Many thanks in advance!!
I will also happily accept any advice as to how to clean up my grammar. I'm still fairly new at this stuff and feel like my stuff is a mess right now :)
It's easy enough to match a string up to but not including the first instance of end:
([^e]|e[^n]|en[^d])*
(And it doesn't even need non-greedy repetition.)
However, that's not what you want. The included JavaScript might include:
variables whose names happen to include the characters end (tendency)
comments (/* Take the values up to the end of the line */)
character strings (if (word == "end"))
and, indeed, the word end itself, which is not a reserved word in js.
Really, the only clean solution is to be able to lex javascript. Fortunately, you don't have to do it precisely, because you're not interpreting it, but even so it is a bit of work. The most annoying part of javascript lexing, like other similar languages, is identifying when / is the beginning of a regular expression, and when it is just division; getting that right requires most of a javascript parser, particularly since it also interacts with the semicolon rule.
To deal with the fact that the included javascript might actually use a variable named end, you have a couple of choices, as far as I can see:
Document the fact that end is a reserved word.
Only recognize end when it appears outside of parentheses and in a place where a statement might start (not too difficult if you end up building enough of a JS parser to correctly identify regular expressions)
Only recognize end when it appears by itself on a line.
This last choice would really simplify your problem a lot, so you might want to think about it, although it's not really very elegant.
1:{key:value}["key"]
2:({key:value})["key"]
I'm wondering how the JS interpreter works on the above codes, and why 1 doesn't work and why 2 works?
I assume you are asking the question because you saw this effect in a JavaScript REPL (shell). You are using a JavaScript shell which assumes the leading "{" begins a block statement instead of an object literal.
For example, if you use the JavaScript interpreter that comes with the Chrome browser, you see the following:
> {key:"value"}["key"]
["key"]
Here, Chrome saw what you entered as a block statement, followed by the expression that was an array of one element, the string "key". So it responded with the result of that expression, namely the array ["key"]
But not all shells work this way. If you use the interpreter with node.js, then #1 will work for you!
$ node
> {key:"value"}["key"]
'value'
>
In interpreters like Chrome, you have to use parentheses to tell it that you want the first part to be an object literal. (This technique, by the way, is guaranteed to work in all shells, including node's).
EDIT
As pointed out in one of the comments, if you use that construct in an expression context anywhere in an actual script, it will produce "value". It's the use in the shell that looks confusing.
This fact was actually exploited in the famous WAT video by Gary Bernhardt.
This question already has answers here:
JSLint reports "Insecure ^" for my regex -- what does that mean?
(3 answers)
Closed 10 years ago.
JavaScript: The Good Parts p41 contains the following regex:
/&([^&;]+);/g
which is used to find all HTML entities such as >. If one validates this code with JSLint it reports
Insecure '^'
While this is correct strictly speaking, I still believe it's fine to ignore it. Or not?
It's warning that the regular expression might match more than expected, and it is correct to warn about it; it will match things like this “&abc def ghi;” despite them being illegal entity names. On the other hand, it is probably not a serious problem in this case (though it strictly depends on what you do after matching); you can disable it in JSLint easily enough.
A better RE would be:
/&(#[0-9]+|#[xX][a-fA-F0-9]+|[a-zA-Z0-9]+);/
I can't remember what other characters are permitted in entity names, alas.
To offer an answer to the actual question. If you know why it is insecure and are okay with it, ignore it. If you are annoyed by JSLint complaining, fix it. ;)
I would consider it secure enough.
I just started to learn JavaScript with the book "Eloquent JavaScript", which is accessible free of charge at eloquentjavascript.net. So far I really like the book, there's just one section I don't understand. It's the one about expressions and statements:
http://eloquentjavascript.net/chapter2.html#p65af5913
I know this topic has been mentioned on StackOverflow before, however, these were more specific questions and I - quite frankly - don't get the whole thing.
In the beginning of the paragraph, the author explains what expressions are: If I understand it correctly, atomic values such as 42 or "23" are being considered expressions. If one applied those values to an operator (as in 42 - 19), this would be considered an expression, too. (I guess because it obviously turns out to be 23, which is an atomic value once again.) I interpret this the following way: Every value - no matter whether it's directly typed in or is yet to be calculated - is being called an expression. Is that correct?
Then the author says the following: "There exists a unit that is bigger than an expression. It is called a statement. [...] Most statements end with a semicolon (;). The simplest kind of statement is an expression with a semicolon after it." As an example he mentions !false; as an example statement. My questions is "What makes this a statement? Just the semicolon at the end?" When I use the JavaScript console, it makes absolutely no difference whether I type that in with or without the semicolon. It always returns true. However, the author says that "[A] statement only amounts to something if it somehow changes the world." So the given example is not even a statement since it "just produce[s] the value [...] true, and then immediately throw[s it] into the bit bucket"? I am really confused now... If I did not entirely mess it up in my head, a statement has to have some "side-effect" (like a declaration of a variable), right?
However, I would be very happy if someone could explain what a statement is. It would also be very helpful if someone could give an example in which the distinction of those terms is actually useful, because right now I cannot even imagine why the author even bothers to introduce these vocabularies. Thank you very much in advance!
A simple, albeit vague, analogy would be a text in a natural language, consisting of phrases grouped into sentences. A phrase, like "it's raining" can form a sentence by itself, like "I won't go out. It's raining." or be a part of a bigger sentence, like in "Terrible weather, it's raining all the time."
That said, the distinction between expressions and statements is very blurred in javascript. Unlike other C-alike languages, you can have not only expressions in statements, but also statements inside expressions:
a = 1 + function(x) { if(x > 1) return 10 } (20)
Some modern javascript programs, such as Jquery, use declaration techniques that basically make them one single expression.
This blurry distinction (not to say confusion) comes from the fact that Javascript, being a C/pascal/algol-like imperative language, was at the same time heavily influenced by functional languages like Lisp, which don't have a notion of "statements". In a functional language, everything is an expression.
To make things more interesting, the semicolon between statements is (sometimes) optional, so that there's no easy way to tell if two expressions belong to one statement or form two distinct ones. Consider:
a = 1 // two
!2 // statements
a = 1 // one
+2 // statement
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I didn't realise it until recently, but I use the Allman style when writing javascript code.
According to http://encosia.com/in-javascript-curly-brace-placement-matters-an-example/ I should be using K&R style. This is because in some situations placement of the curly bracket on the next line can cause problems.
The problem for me is that I've grown rather fond of the Allman style and would rather not change.
So, my question(s)
Is it true that the allman style can cause errors due to the
placement of curly brackets in javascript? How about jquery?
Is there any trick that would enable me to use Allman style
without problems due to curly brackets?
Are there any other problems associated with using these styles?
Is it true that the allman style can cause errors due to the placement
of curly brackets in javascript?
Yes, it is. As your link explains, return statements followed by a newline will confuse the parser as it tries to insert a semicolon. This behavior is not limited to returning object literals, though. The following function:
function foo()
{
return
"bar";
}
Will also return undefined.
How about jquery?
The situation remains exactly the same whether or not jQuery is included.
Is there any trick that would enable me to use Allman style without
problems due to curly brackets?
Yes, do not use Allman style with object literals. Consider you want to assign an object literal to a variable. Are you really going to write:
var foo =
{
bar: "quux"
};
Or will you go for:
var foo = {
bar: "quux"
};
IMHO the second snippet is more readable than the first. You can continue using Allman style with the braces inside for, if, while, function, etc., but make an exception for object literals.
Are there any other problems associated with using these styles?
return is quite a special case, because it is valid with or without an argument. When confronted with a lone return statement on one line, the parser cannot tell if it should add a semicolon to make the single-line statement valid, or continue to the next lines and hope for the best.
For this reason, I think this behavior only becomes a problem with return and maybe throw, not other statements.
Keep in mind ECMAScript specification regarding 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.
I laugh at the suggestion above that it is "convenient"...
While you technically could could continue using Allman formatting in cases not covered above, I would preach consistency. Personally I'm a fan of Google JS styleguide - sections relevant to your question are the code formatting and semicolons ones. The examples listed there are worth checking out.