Friday, December 7, 2007

JavaScript Format

I'm pretty picky about my code, so I want to detail my pet peeves and preferences. I'll assume that everyone knows what objects, arrays, strings, regular expressions (or "regexes"), numbers, functions, classes, methods, procedures, and properties are.


Operators
I put spaces on each side of my operators (=, +, -, *, /, %, ?, :, &&, ||, ==, !=, ===, !==, <, <=, >, >=, ^, ~, &, |, <<, >>, >>>), except for commas, colons used for assignment/labeling, exclamation points, and increment/decrement signs (++ and --). Commas and assignment/label colons get no spaces before and one space after.


Most JavaScript strings are enclosed in single quotes. This makes it easier to write HTML attributes and user-friendly quotes from JavaScript, and causes problems only if apostrophes get involved (in which case double quotes may be used). Alternatively, either type of quote may be escaped with a single backslash, and this is valid for both types within both types ("so \'this\' is valid").


Each line which would end with a semicolon in most languages will in my JavaScript. This way, code is more likely to be compatible in future versions of JavaScript, readability is enhanced (I believe), and some rare ambiguous situations are clarified for the browser. (I can't think of any of those ambiguous situations offhand, so you'll have to take my word for it and keep your eyes open.)


Curly brackets are always reason to break the line if there's anything in them; round brackets, square brackets, and ternary operators are only when their contents get too long for the screen. All such containers increase the indentation of any contained lines by one.


Iterators
Most people use alphabetical iterator identifiers (i, j, k, etc.) in their for loops. However, I got very frustrated and embarrassed (in my high school Computer Science class) by a simple bug - a spelling error - and now use numeric identifiers (i0, i1, i2, etc.) to make the difference between my first (i or i0) and second (j or i1) visually obvious. I also have a higher range of identifiers that don't cause confusion available; whereas someone else's 19th iterator might be called "zi," mine would simply be "i18."


When needed, my program-initialization procedure will be directly assigned to window.onload:
<html>
   <head>
      <title>Titled Document</title>
      <script type="text/javascript">
         function main(){
            //
         }
      </script>
   </head>
   <body onload="main();">
      
   </body>
</html>



Here's a demonstration of everything mentioned above:
var one = 1;
var two = one * 2;
var three = two + one;
var yup = true;
if(!yup || (three <= two)){
   alert('This can't be happening!');
}
for(var i0 = 0; i0 < 10; i0++){
   //
}
var object = {
   numbers: [ //This array really isn't long enough to break, but
      one,    //I want to show what I mean.
      two,    //(This applies to argument lists, too.)
      three
   ],
   do: function(){
      alert(function dummy(){
            //This is just a dummy.
         });//The round brackets don't break, but the curly ones do.
   }
}
var something = yup ? object : null;
switch(something){
   case object:
      //
      break;
   case null:
      //
      break;
   default:
      //
}
window.onload = function(){
   //Do something.
};

No comments: