I have been unable to find any reference to this statement in any book, manual, or site. As far as I can tell, it functions exactly as a // comment. For example:
console.log("1");
--> console.log("2");
console.log("3");
will print
1
3
What I'm curious about is exactly what the difference between --> and // is, if any exists, and also why --> seems to completely absent from all the JavaScript references I've seen - the only reason I found out about it at all was because I accidentally typed it into Adobe Dreamweaver, and it was highlighted as a comment. Thanks!
Edit: Here is a functional jsFiddle demonstrating the behavior.
Edit 2: I've tested further, and I've discovered a few things.
This only works if there are exactly two dashes. -> and ---> will throw errors.
This only works with a "greater than" symbol. --< will throw an error.
This will not work in the middle of or at the end of a line. console.log("1"); --> console.log("2"); will throw an error.
My guess is that the JavaScript engine, forgiving as always, is silently ignoring the line because it looks like the end of an HTML comment (<!-- -->). JavaScript inlined in HTML has historically been wrapped in an HTML comment so that browsers that don't support JavaScript would not try to parse it.
Edit:
I've done some research, and this is indeed the case.
From V8's scanner.cc:
If there is an HTML comment end '-->' at the beginning of a
line (with only whitespace in front of it), we treat the rest
of the line as a comment. This is in line with the way
SpiderMonkey handles it.
From Rhino's Comment.java:
JavaScript effectively has five comment types:
// line comments
/* block comments */
/** jsdoc comments */
<!-- html-open line comments
^\s*--> html-close line comments
The first three should be familiar to Java programmers. JsDoc comments
are really just block comments with some conventions about the formatting
within the comment delimiters. Line and block comments are described in the
Ecma-262 specification.
Note that the --> comment is not part of the Ecma-262 specification.
This is not a comment. If you see it as a comment inside of code, then its probably showing as some kind of hanging chad HTML comment instead of the normal "//".
What's happening in this case is you are comparing using the greater than and then subtracting 1. Here are some examples...
var x = 3; var y = 3; console.log(x --> y);
false and x is now 2
If you place the normal comment characters "//", you'll get a syntax error (which you should)
The reason this is working as a comment is because it is returning as undefined. This is not safe to use as a comment. Oddly enough, it works fine in Chrome and you can throw all kinds of characters at it if you start the line with "-->".
--> something for nothing ~!####%$#%^$&%^&*()_+_=-=[]\];'\||?>;';;; alert('test'),,143187132458
However, within IE 11, it is always a syntax error. Very cool find
Related
I recently had to fix a bug that manifested sometimes in Internet Explorer. The bug was that, sometimes, the parser choked on code like
<script type="text/javascript">
<!-- // comments -->
/*...*/
</script>
Which we fixed by correcting the comment.
My question is: is "<!--" valid javascript code, or not? I tried testing it with firebug, and it only says" Undefined". JSFiddle didn't faze. IE only choked on it some of the times (reloading the page in question would show up the result of the script involved).
While knowing that, for historical reasons, an HTML comment inside js could be valid depending on its exact position and the phase of the moon is indeed useful, I was more interested in answers like "var <!-- foo is valid js code, but <!-- on its own is not. Here's why:..."
I did some analysis in firebug:
var x = 2;
var y = 3;
var z = 0;
console.log(x);
console.log(y);
y<!--x;
console.log(x);
console.log(y);
z = y<! --x;
console.log(x);
console.log(y);
console.log(z);
resulting in the following:
2
3
2
3
1
3
false
The difference between the first and second tries is interesting.
I then tried
z = (y <!--x);
console.log(z);
Which failed with
SyntaxError: missing ) in parenthetical
First to answer your question on Is <!-- valid JavaScript: No, it is not, in none of the forms you gave in your question. This is because it is not valid according to the JavaScript BNF grammar which you can find here: http://tomcopeland.blogs.com/EcmaScript.html
If you are interested, here's why you do see it inside script blocks: It is the HTML comment character. You do see it very often within script tags like this:
<script>
<!--
.. JavaScript code...
// -->
</script>
The reason is that old browsers (and with "old" I mean "stone age" like Netscape 1.0) that do not even support JavaScript and would otherwise just show the code on the screen. By doing it this way those older browsers treat the JavaScript as HTML comments and do not show it. Newer browsers ignore this and just run the JavaScript.
This is how it actually works (from http://www.w3.org/TR/html401/interact/scripts.html#h-18.3.2): The JavaScript engine allows the string <!-- to occur at the start of a SCRIPT element, and ignores further characters until the end of the line. JavaScript interprets // as starting a comment extending to the end of the current line. This is needed to hide the string --> from the JavaScript parser.
Because all browsers nowadays support JavaScript (even if it is turned off) you do not need to do this anymore. It is actually bad practice to do so because of these reasons (from http://www.javascripttoolbox.com/bestpractices/#comments):
Within XHTML documents, the source will actually be hidden from all browsers and rendered useless
-- is not allowed within HTML comments, so any decrement operations in script are invalid
An even deeper explanation and all the cons and pro's can be found here: http://lachy.id.au/log/2005/05/script-comments
In older browsers, it was required to have these comments inserted because the browsers couldn't parse the javascript properly. it would try to literally parse the javascript as html which caused script execution failures.
Today, browsers don't need this.
It's not.
If you go to the standard, you'll see that a < can only exist in a RelationalExpression, which <!-- is not as it hasn't got anything on the left-hand side.
Comments in Javascript are like other C-type languages (// for single line, /* */ for blocks.
I have some big set of different javascript-snippets (several thousands), and some of them have some stupid errors in syntax (like unmatching braces/quotes, HTML inside javascript, typos in variable names).
I need a simple way to check JS syntax. I've tried JSLint but it send too many warnings about style, way of variable definitions, etc. (even if i turn off all flags). I don't need to find out style problems, or improve javascript quality, i just need to find obvious syntax errors. Of course i can simply check it in browser/browser console, but i need to do it automatically as the number of that snippets is big.
Add:
JSLint/JSHint reports a lot of problems in the lines that are not 'beauty' but working (i.e. have some potential problems), and can't see the real problems, where the normal compiler will simply report syntax error and stop execution. For example, try to JSLint that code, which has syntax errors on line 4 (unmatched quotes), line 6 (comma required), and line 9 (unexpected <script>).
document.write('something');
a = 0;
if (window.location == 'http://google.com') a = 1;
document.write("aaa='andh"+a+"eded"');
a = {
something: ['a']
something2: ['a']
};
<script>
a = 1;
You could try JSHint, which is less verbose.
Just in case anyone is still looking you could try Esprima,
It only checks syntax, nothing else.
I've found that SpiderMonkey has ability to compile script without executing it, and if compilation failed - it prints error.
So i just created small wrapper for SpiderMonkey
sub checkjs {
my $js = shift;
my ( $js_fh, $js_tmpfile ) = File::Temp::tempfile( 'XXXXXXXXXXXX', EXLOCK => 0, UNLINK => 1, TMPDIR => 1 );
$| = 1;
print $js_fh $js;
close $js_fh;
return qx(js -C -f $js_tmpfile 2>&1);
}
And javascriptlint.com also deals very good in my case. (Thanks to #rajeshkakawat).
Lots of options if you have an exhaustive list of the JSLint errors you do want to capture.
JSLint's code is actually quite good and fairly easy to understand (I'm assuming you already know JavaScript fairly well from your question). You could hack it to only check what you want and to continue no matter how many errors it finds.
You could also write something quickly in Node.js to use JSLint as-is to check every file/snippet quickly and output only those errors you care about.
Just use node --check filename
Semantic Designs' (my company) JavaScript formatter read JS files and formats them. You don't want the formatting part.
To read the files it will format, it uses a full JavaScript parser, which does a complete syntax check (even inside regular expressions). If you run it and simply ignore the formatted result, you get a syntax checker.
You can give it big list of files and it will format all of them. You could use this to batch-check your large set. (If there are any syntax errors, it returns a nonzero error status to a shell).
I'm making a library, and I often inspect the result of Closure Compiler's output to see how it's doing things (I do have unit tests, but I still like to see the compiled code for hints of how it could compress better).
So, I found this very weird piece of code, which I never seen before.
variable : {
some();
code()
}
Note: this is not an object literal! Also, there is no ? anywhere that would make it a ?: conditional.
That code is in a regular function block (an IIFE).
variable, in this case, is an undefined variable. There's no code making it true, false, or whatever, and just to make sure, I put a console.log in there and indeed, I get a ReferenceError.
Please do note that I test my code in IE8 too, so this isn't just in modern browsers. It seems to be standard, plain old javascript.
So let's experiment with it. Firing up Chrome's console, I get this:
undeclaredVariable:{console.log('does this get logged?')} // yes it does.
trueValue:{console.log('what about this?')} // same thing.
falseValue:{console.log('and this?')} // same thing.
but then...
(true):{console.log('does this work too?')} // SyntaxError: Unexpected token :
...and...
so?{console.log('is this a conditional?')}:{alert(123)} // Unexpected token .
So what does it do?
thisThing:{console.log('is used to declare a variable?')}
thisThing // ReferenceError: thisThing is not defined
Please, I'd love it if someone could explain to me what this code is meant to do, or at least what it does.
It is a label
Provides a statement with an identifier that you can refer to using a
break or continue statement.
For example, you can use a label to identify a loop, and then use the
break or continue statements to indicate whether a program should
interrupt the loop or continue its execution.
Another common place you see it is when people stick the wonderful and useless javascript: on event handlers.
This is a label (the bit ending with a colon) followed by a block (the code surrounded by the curly brackets).
Blocks usually follow control statements, like if(...) { /*block*/ }, but they can also simply stand on their own, as in your example.
Labels allow jumping up several loops at a time with a continue or break; see the linked MDN page for several examples, such as:
var itemsPassed = 0;
var i, j;
top:
for (i = 0; i < items.length; i++){
for (j = 0; j < tests.length; j++)
if (!tests[j].pass(items[i]))
continue top;
itemsPassed++;
}
Here, top: is a label that code inside the inner loop can jump to, in order to escape to the outer loop.
For the sake of anyone who doesn't know what JSON is, and sees a colon in what might actually be an object, and is trying to figure out what it is, and finds this discussion, a colon is also used in JSON. There is a practice of embedding functions in a JSON object. Which might be confusing (As it was to me) for anyone who happens to see this for the first time. (Everyone isn't born with the knowledge of JSON and JavaScript programmed into their brains.) So if you find yourself at this discussion, and you think that every time you see a colon in JavaScript, that it's a label, it might not be. It might be that it's a colon after a label, OR it might be part of JSON. In fact, a colon in JSON being shown as a string, is a lot more common than a label. JSON in the form of an object, will be displayed as [object Object], with all the content hidden. So, unless the JSON is in the form of a string, and you display an object to the console (console.log(object)) all you will see is [object Object]. It is common practice to write JavaScript code, wrapped in an object. In that case you will see the JSON in the form of code. That's when you'll ask yourself, "What is this? and what is that colon for?" Then you'll find yourself at this discussion, and be told that it's a label, when it's really part of JSON. The topic of this discussion is worded: "Please explain this usage of a colon in javascript", and then the "correct answer" is marked as having to do with a label. The correct answer is that a colon can be used in more than one way. So, if you don't know what JSON is, or think you know (like I did, but didn't really understand) read about it here:
JSON.org
That is just a label.
you can use continue [label name] (or break) in a loop to go to a label.
More explanations of what they are can be seen throughout the interwebs.
it is used for labeling an statement in jsvascript.check more detail here.
the labeled statement can be used with break and continue later.
This is my JavaScript (much stripped down):
function addContent() {
var content = [];
content.append(
makeVal({
value : 1
})
); // Generates lint message
}
Running a lint program over this, I get the message
unexpected end of line; it is ambiguous whether these lines are part of the same statement
on line 7. If I concatenate lines 6 and 7 the message goes away.
Can anyone explain where this ambiguity is? It seems to me that the parenthesis on line 7 is unambiguously closing the call to append().
It looks that way to me, too. Sounds like a bug in the lint program you're using.
You can understand why it would wonder, because the call to makeVal fits the profile of code that's relying on semicolon insertion — unless you look correctly at the wider context and realize it's within argument list for the append call. Seems to me the lint program is not actually parsing the language, just looking for patterns, which is going to mean it's going to have both false positives and false negatives.
I have a minified/packed javascript file which is causing problems. The issue is that the non-packed input file has some missing semicolons somewhere which aren't a problem when there's line breaks, but when the file is packed, the line breaks are removed and that causes a parser error. For example:
//input
var x = function() {
doSomething();
} // note: no semicolon
var y = 'y';
//----
// output
var x=function(){doSomething();}var y='y';
// error here: ^
The strange thing is that when I do a replace on the output file to replace all semicolons with a semicolon and a new line, the file works! This is making it ludicrously hard to find the error, since AFAIK, I can't think of any situation where a line break after a semicolon should change anything. Any ideas about why doing this replace would make it work?
Uh... Have you tried JSLint?
When there's a line break, there's an implied semi-colon.
Use jslint to check your code. If you do this and get it passing with regards to semicolons, it should pack correctly.
In JavaScript, semicolons are implicitly added at newlines. This introduces situations that can be ambiguous. This blog post: http://robertnyman.com/2008/10/16/beware-of-javascript-semicolon-insertion/ describes the problem succinctly and gives an example.
JSlint is a good solution. Also, some code editors will find these kinds of errors for you. If I recall correctly, NetBeans catches these in realtime, as you type. I believe Komodo and Aptana do as well.