What happens to JavaScript literals (strings, numbers) that are not bound (aka assigned) to a variable ?
// A comment
"Practically, also a comment"
var assigned = "something"
53
423.0022
NaN
"does it impact performance"
// or is it treated just like a comment?
The browser appears to ignore them, but I couldn't find a specific rule in the spec
These are "expression statements". Such expressions are evaluated, but since they are not assigned, their value is not stored. JavaScript engines are likely to detect those that have no side effects, and eliminate them as if they were never there.
But still at least one of those has an effect:
"use strict";
This has the meaning of a JavaScript directive
From the EcmaScript specification:
A Use Strict Directive is an ExpressionStatement in a Directive Prologue whose StringLiteral is either the exact code unit sequences "use strict" or 'use strict'.
Also note that other string literals may have a special meaning when used in the directive prologue:
Implementations may define implementation specific meanings for ExpressionStatement productions which are not a Use Strict Directive and which occur in a Directive Prologue.
It's just an expression statement that evaluates - without side effects - to a value that is discarded.
You can see it's the result of the statement if you try this in eval or a REPL.
The values are stored in memory, until they get cleaned up by the Garbage collector, since nothing is pointing to that place in memory.
Since the value is not being stored (i.e. no space is being allocated to hold your literal), it is more or less being ignored by the browser, and also no overhead for the garbage collector. At least the function of your code does not change. Your javascript file will of course be a tiny bit larger because it contains more (useless) text.
It appears to treat them as variables being inserted to nothing. It treats them as if they don't exist anyway. Try it:
function myFunction() {
"comment"
//Or comment
alert("hello");
}
<html>
<body>
<button onclick="myFunction()">Call Javascript</button>
</body>
</html>
As you can see, nothing happens when the empty string is there. This is an interesting question, so I would be very interested in hearing any other results.
Related
In Node.js's REPL (tested in SpiderMonkey as well) the sequence
var foo = null;
(foo) = "bar";
is valid, with foo subsequently equal to "bar" as opposed to null.
This seems counterintuitive because one would think the parenthesis would at least dereference bar and throw Invalid left-hand side in assignment`.
Understandably, when you do anything interesting it does fail in aforementioned way.
(foo, bar) = 4
(true ? bar : foo) = 4
According to ECMA-262 on LeftHandExpressions (so far as I can interpret) are no valid non-terminals that would lead to a parenthetical being accepted.
Is there something I'm not seeing?
It's valid indeed. You're allowed to wrap any simple assignment target in parenthesis.
The left hand part of the = operation is a LeftHandSideExpression as you correctly identified. This can be tracked down through the various precendence levels (NewExpression, MemberExpression) to a PrimaryExpression, which in turn might be a CoverParenthesizedExpressionAndArrowParameterList:
( Expression[In, ?Yield] )
(actually, when parsed with target PrimaryExpression, it's a ParenthesizedExpression).
So it's valid by the grammar, at least. Whether it's actually valid JS syntax is determined by another factor: early error static semantics. Those are basically prose or algorithmic rules that make some production expansions invalid (syntax errors) in certain cases. This for example allowed the authors to reuse the array and object initialiser grammars for destructuring, but only applying certain rules. In the early errors for assignment expressions we find
It is an early Reference Error if LeftHandSideExpression is neither an ObjectLiteral nor an ArrayLiteral and IsValidSimpleAssignmentTarget of LeftHandSideExpression is false.
We can also see this distinction in the evaluation of assignment expressions, where simple assignment targets are evaluated to a reference that can be assigned to, instead of getting the destructuring pattern stuff like object and array literals.
So what does that IsValidSimpleAssignmentTarget do to LeftHandSideExpressions? Basically it allows assignments to property accesses and disallows assignments to call expressions. It doesn't state anything about plain PrimaryExpressions which have their own IsValidSimpleAssignmentTarget rule. All it does is to extract the Expression between the parentheses through the CoveredParenthesizedExpression operation, and then again check IsValidSimpleAssignmentTarget of that. In short: (…) = … is valid when … = … is valid. It'll yield true only for Identifiers (like in your example) and properties.
As per #dlatikay's suggestion, following an existing hunch, research into CoveredParenthesizedExpression yielded a better understanding of what's happening here.
Apparently, the reason why a non-terminal cannot be found in the spec, to explain why (foo) is acceptable as a LeftHandExpression, is surprisingly simple. I'm assuming you understand how parsers work, and that they operate in two separate stages: Lexing and Parsing.
What I've learned from this little research tangent is that the construct (foo) is not technically being delivered to parser, and therefor the engine, as you might think.
Consider the following
var foo = (((bar)));
As we all know, something like this is perfectly legal. Why? Well you visually can just ignore the parenthesis while the statement remains making perfect sense.
Similarly, here is another valid example, even from a human readability perspective, because the parentheses only explicate what PEMDAS already makes implicit.
(3 + ((4 * 5) / 2)) === 3 + 4 * 5 / 2
>> true
One key observation can be loosely derived from this, given an understanding of how parsers already work. (remember, Javascript still is being parsed (read: compiled) and then run) So in a direct sense, these parentheses are "stating the obvious".
So all that being said, what exactly is going on?
Basically, parentheses (with the exception of function parameters) are collapsed into proper groupings of their containing symbols. IANAL but, in lay man's terms, that means that parentheses are only interpreted to guide the parser how to group what it reads. If the context of the parentheses is already "in order", and thus does not require any tweaking of the emitted AST, then the (machine) code is emitted as if those parentheses did not exist at all.
The parser is more or less being lazy, assuming the parens are impertinent. (which in this edge-case, is not true)
Okay, and where exactly is this happening?
According to 12.2.1.5 Static Semantics: IsValidSimpleAssignmentTarget in the spec,
PrimaryExpression: (CoverParenthesizedExpressionAndArrowParameterList)
Let expr be CoveredParenthesizedExpression of CoverParenthesizedExpressionAndArrowParameterList.
Return IsValidSimpleAssignmentTarget of expr.
I.E. If expecting primaryExpression return whatever is inside the parenthesis and use that.
Because of that, in this scenario, it does not convert (foo) into CoveredParenthesizedExpression{ inner: "foo" }, it converts it simply into foo which preserves the fact that it is an Identifier and thus syntactically, while not necessarily lexically, valid.
TL;DR
It's wat.
Want a little more insight?
Check out #Bergi's answer.
Reading Crockfords The Elements of JavaScript Style I notice he prefers defining variables like this:
var first='foo', second='bar', third='...';
What, if any benefit does that method provide over this:
var first='foo';
var second='bar';
var third='...';
Obviously the latter requires more typing but aside from aesthetics I'm wondering if there is a performance benefit gained by defining with the former style.
Aside of aesthetics, and download footprint, another reason could be that the var statement is subject to hoisting. This means that regardless of where a variable is placed within a function, it is moved to the top of the scope in which it is defined.
E.g:
var outside_scope = "outside scope";
function f1() {
alert(outside_scope) ;
var outside_scope = "inside scope";
}
f1();
Gets interpreted into:
var outside_scope = "outside scope";
function f1() {
var outside_scope; // is undefined
alert(outside_scope) ;
outside_scope = "inside scope";
}
f1();
Because of that, and the function-scope only that JavaScript has, is why Crockford recommends to declare all the variables at the top of the function in a single var statement, to resemble what will really happen when the code is actually executed.
Since JavaScript is generally downloaded to the client browser, brevity is actually quite a valuable attribute. The more bytes you have to download, the slower it gets. So yes, there is a reason apart from aesthetics, if not a massive one.
Similarly, you'll see people preferring shorter variable names to longer.
Personally, I don't bother minimising whitespace, as there are minimisers that can do this sort of thing for you (for example in YUI), and lack of indentation and spacing leads to less maintainable code.
No difference in semantics and no measurable difference in performance. Write whichever is clearest.
For simple examples like:
var first= 'foo', second= 'bar', third= 'bof';
the concise single-statement construct is probably a win for readability. On the other hand you can take this much too far and start writing half your program inside a single var statement. Here's a random example plucked from the jQuery source:
var name = match[1],
result = Expr.attrHandle[ name ] ?
Expr.attrHandle[ name ]( elem ) :
elem[ name ] != null ?
elem[ name ] :
elem.getAttribute( name ),
value = result + "",
type = match[2],
check = match[4];
I find this (by no means the worst example) a bit distasteful. Longer examples can get quite hard to read upwards (wait, I was in a var statement?) and you can end up counting the brackets to try to work out what's a multi-line expression and what's just an extended var block.
I believe that what he is going for is declaring all variables as abosultely the first statement in a function (You'll notice that JSLint complains about this if you use it and don't declare them on the first line). This is because of JavaScript's scope declaration limitations (or quirks). Crockford emphasizes this as good practice for maintainable JavaScript code. The second example declares them at the top, but not in the first execution statement. Personally, I see no reason as why to prefer the first over the second, but following the first does enforce that all variables are declared before doing anything else in the function.
David is right that the larger the script the more time it will take to down load, but in this case the difference between the two is minimal and can be handled by using YUI compress etc.
It's a personal programming style choice.
On the one hand there is readability, wherein placing each variable declaration on a separate line makes it more obvious what's going on.
On the other hand, there is brevity, wherein you're eliminating transmitting a few extra bytes over the network. It's generally not enough to worry about, unless you're dealing with slow networks or limited memory on the client browser side.
Brevity is also known as laziness on the part of the programmer, which is one reason that many purists avoid it.
It all comes down to personal taste or a set of style-guides, your development team follows. If you are serving JavaScript yourself, you usually compress or minify your script(s) into one long string in one single file. So the whole you-are-saving-bytes-and-your-scripts-download-faster argument is, well, not an argument :)
I usually declare my variables like this: (a style you didn't mention)
var something,
somethingElse,
evenMoreSomething,
andAnotherThing;
A statement like "var" is not minified/compressed.Every time you place a var, instead of a comma you lose 4 chars, if I count right.
In this test, I am looking at two different ways of function expressions; using the exclamation point unary operator and using brackets.
The following are the 2 tests:
var f = !function() {};
var f = (function() {});
Given the results below, I was intrigued when I saw that the unary operator test was ~5261% faster than the brackets test in Firefox.
What sort of optimization is going on that amounts to such a significant increase in performance in Firefox, dwarfing the other browsers?
The first one is resulting in a boolean, and the second one a function. There doesn't seem to be much real-world significance to your test.
"What sort of optimization is going on that amounts to such a significant increase in performance in Firefox, dwarfing the other browsers?"
I suppose Firefox has an optimization that avoids creation of the function object since it is never actually used, but that's just a guess.
Here's an updated jsPerf. This one adds two tests that create boolean values. Notice that they're very close to the "Exclamation" test in Firefox.
This lends support to the idea that Firefox has this particular optimization.
If you put this in a more "real-life" example, the difference is no longer really imporant.
Those expressions are most likely used to create an outer function context to encapsulate your code from the global context, like
!function() {
}();
(function() {
}());
See results for that here: http://jsperf.com/function-expressions/2
You actually double the work for the engine there. But assigning a function to a variable you implicitly create a function expression
var f = function() {};
Also applying the ! operator, is unnecessary work.
You're getting somewhere around 1e9 operations per second on the "exclamation" case. Your CPU probably does somewhere around 1-4 billion clock ticks per second. so that case is taking around 1-4 clock ticks.
What that means is that the entire thing got optimized away to "f = false" by the JIT. Most likely because type inference detected that unary "!" is always followed by an object, and optimized it to "false".
One reason it's slower in Chrome is that in Chrome there are objects for which unary "!" returns true, so the optimization I describe above is invalid there.
I was reading In JavaScript, what is the advantage of !function(){}() over (function () {})()? then it hit me, why use :
(function(){})() or !function(){}() instead of just function(){}()?
Is there any specific reason?
It depends on where you write this. function(){}() by itself will generate a syntax error as it is evaluated as function declaration and those need names.
By using parenthesis or the not operator, you enforce it to be interpreted as function expression, which don't need names.
In case where it would be treated as expression anyway, you can omit the parenthesis or the operator.
I guess you are asking why use:
var fn = (function(){}());
versus:
var fn = function(){}();
The simple answer for me is that often the function on the RHS is long and it's not until I get to the bottom and see the closing () that I realise I've been reading a function expression and not a function assignment.
A full explanation is in Peter Michaux's An Important Pair of Parens.
A slight variation on RobG's answer.
Many scripts encompass the entire program in one function to ensure proper scoping. This function is then immediately run using the double parentheses at the end. However, this is slightly different then programs which define a function that can be used in the page but not run initially.
The only difference between these two scenarios is the last two characters (the addition of the double parentheses). Since these could be very long programs, the initial parenthesis is there to indicate that "this will be run immediately."
Is it necessary for the program to run? No. Is it helpful for someone looking at the code and trying to understand it? Yes.
The following code illustrates an object literal being assigned, but with no semicolon afterwards:
var literal = {
say: function(msg) { alert(msg); }
}
literal.say("hello world!");
This appears to be legal, and doesn't issue a warning (at least in Firefox 3). Is this completely legal, or is there a strict version of JavaScript where this is not allowed?
I'm wondering in particular for future compatibility issues... I would like to be writing "correct" JavaScript, so if technically I need to use the semicolon, I would like to be using it.
Not technically, JavaScript has semicolons as optional in many situations.
But, as a general rule, use them at the end of any statement. Why? Because if you ever want to compress the script, it will save you from countless hours of frustration.
Automatic semicolon insertion is performed by the interpreter, so you can leave them out if you so choose. In the comments, someone claimed that
Semicolons are not optional with statements like break/continue/throw
but this is incorrect. They are optional; what is really happening is that line terminators affect the automatic semicolon insertion; it is a subtle difference.
Here is the rest of the standard on semicolon insertion:
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.
The YUI Compressor and dojo shrinksafe should work perfectly fine without semicolons since they're based on a full JavaScript parser. But Packer and JSMin won't.
The other reason to always use semi-colons at the end of statements is that occasionally you can accidentally combine two statements to create something very different. For example, if you follow the statement with the common technique to create a scope using a closure:
var literal = {
say: function(msg) { alert(msg); }
}
(function() {
// ....
})();
The parser might interpret the brackets as a function call, here causing a type error, but in other circumstances it could cause a subtle bug that's tricky to trace. Another interesting mishap is if the next statement starts with a regular expression, the parser might think the first forward slash is a division symbol.
JavaScript interpreters do something called "semicolon insertion", so if a line without a semicolon is valid, a semicolon will quietly be added to the end of the statement and no error will occur.
var foo = 'bar'
// Valid, foo now contains 'bar'
var bas =
{ prop: 'yay!' }
// Valid, bas now contains object with property 'prop' containing 'yay!'
var zeb =
switch (zeb) {
...
// Invalid, because the lines following 'var zeb =' aren't an assignable value
Not too complicated and at least an error gets thrown when something is clearly not right. But there are cases where an error is not thrown, but the statements are not executed as intended due to semicolon insertion. Consider a function that is supposed to return an object:
return {
prop: 'yay!'
}
// The object literal gets returned as expected and all is well
return
{
prop: 'nay!'
}
// Oops! return by itself is a perfectly valid statement, so a semicolon
// is inserted and undefined is unexpectedly returned, rather than the object
// literal. Note that no error occurred.
Bugs like this can be maddeningly difficult to hunt down and while you can't ensure this never happens (since there's no way I know of to turn off semicolon insertion), these sorts of bugs are easier to identify when you make your intentions clear by consistently using semicolons. That and explicitly adding semicolons is generally considered good style.
I was first made aware of this insidious little possibility when reading Douglas Crockford's superb and succinct book "JavaScript: The Good Parts". I highly recommend it.
In this case there is no need for a semicolon at the end of the statement. The conclusion is the same but the reasoning is way off.
JavaScript does not have semicolons as "optional". Rather, it has strict rules around automatic semicolon insertion. Semicolons are not optional with statements like break, continue, or throw. Refer to the ECMA Language Specification for more details; specifically 11.9.1, rules of automatic semicolon insertion.
Use JSLint to keep your JavaScript clean and tidy
JSLint says:
Error:
Implied global: alert 2
Problem at line 3 character 2: Missing
semicolon.
}
The semi-colon is not necessary. Some people choose to follow the convention of always terminating with a semi-colon instead of allowing JavaScript to do so automatically at linebreaks, but I'm sure you'll find groups advocating either direction.
If you are looking at writing "correct" JavaScript, I would suggest testing things in Firefox with javascript.options.strict (accessed via about:config) set to true. It might not catch everything, but it should help you ensure your JavaScript code is more compliant.
This is not valid (see clarification below) JavaScript code, since the assignment is just a regular statement, no different from
var foo = "bar";
The semicolon can be left out since JavaScript interpreters attempt to add a semicolon to fix syntax errors, but this is an extra and unnecessary step. I don't know of any strict mode, but I do know that automated parsers or compressors / obfuscators need that semicolon.
If you want to be writing correct JavaScript code, write the semicolon :-)
According to the ECMAscript spec, http://www.ecma-international.org/publications/standards/Ecma-262.htm, the semicolons are automatically inserted if missing. This makes them not required for the script author, but it implies they are required for the interpreter. This means the answer to the original question is 'No', they are not required when writing a script, but, as is pointed out by others, it is recommended for various reasons.