JavaScript Style: Whitespace

Introduction

Image from Pluralsight

Image from Pluralsight

Good code is not just functional, but also elegant. Elegant code must be:

In a series of posts, we'll discuss coding style for the JavaScriptlanguage. In this second post, we'll focus on style guidelines for whitespace.

Summary

The style guidelines for JavaScript whitespace are broken down into the following categories:

  • Indentation
  • Spaces Around
  • Spaces Before
  • Spaces After
  • Spaces Not Allowed
  • Blank Lines
  • Other

Each category is is explained below. Must you follow these guidelines? No. Should you? Yes.

Indentation

The indentation guidelines for JavaScript are:

  • Require indentation with four (4) spaces
  • Disallow tabs for indentation

For example, this is good:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    function Log() {

        var now,                //  current date/time
            elapsed,            //  elapsed milliseconds since we initialized the stats
            messagesPerSec,     //  number of messages/sec since initialization
            charsPerSec,        //  number of message character/sec since initialization
            idList,             //  the comma-delimited list of ids
            prop;               //  an object property

        now = Now();
        elapsed = now - this.start;
        messagesPerSec = ( this.messages / ( elapsed / 1000 ) );
        charsPerSec = ( this.chars / ( elapsed / 1000 ) );

        for ( prop in this.ids ) {
            if ( this.ids.hasOwnProperty( prop ) ) {
                if ( !idList ) {
                    idList = prop;
                } else {
                    idList = idList + "," + prop;
                }
            }
        }

        options.log( "SOCKET(" + idList + "): Stats - " + messagesPerSec.toFixed( 1 ) + " msg/sec, " + charsPerSec.toFixed( 0 ) + " char/sec" );
    }

and this is bad:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    function Log() {

      var now,              //  current date/time
        elapsed,            //  elapsed milliseconds since we initialized the stats
        messagesPerSec,     //  number of messages/sec since initialization
        charsPerSec,        //  number of message character/sec since initialization
        idList,             //  the comma-delimited list of ids
        prop;               //  an object property

      now = Now();
      elapsed = now - this.start;
      messagesPerSec = ( this.messages / ( elapsed / 1000 ) );
      charsPerSec = ( this.chars / ( elapsed / 1000 ) );

      for ( prop in this.ids ) {                  
        if ( this.ids.hasOwnProperty( prop ) ) {
          if ( !idList ) {
            idList = prop;                  //  BAD: indentation uses two (2) spaces
          } else {                          //  BAD: indentation uses tabs (trust me on this one)
            idList = idList + "," + prop;
          }
        }
      }

      options.log( "SOCKET(" + idList + "): Stats - " + messagesPerSec.toFixed( 1 ) + " msg/sec, " + charsPerSec.toFixed( 0 ) + " char/sec" );
    }

Spaces Around

Spaces are required around:

  • The content of square brackets - []
  • The content of parentheses - ()
  • The content of curly braces - {}
  • Infix operators

For example, this is good:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    function getDaysInMonth( month, year ) {

        var monthDays,
            days;

        monthDays = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];

        if ( month === 2 ) {

            // february, taking leap years into account
            if ( year % 400 === 0 ) {
                days = 29;
            } else if ( ( year % 4 === 0 ) && ( year % 100 !== 0 ) ) {
                days = 29;
            } else {
                days = 28;
            }
        } else {

            //  all other months
            days = monthDays[ month - 1 ];
        }

        return { "days": days };
    }

and this is bad:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    function getDaysInMonth(month, year) {

        var monthDays,
            days;

        monthDays=[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

        if (month===2) {                //  BAD: no spaces around () content

            // february, taking leap years into account
            if (year%400===0) {
                days=29;
            } else if ((year%4===0)&&(year%100!==0)) {
                days=29;
            } else {
                days=28;                //  BAD: no spaces around infix operator
            }
        } else {

            //  all other months
            days=monthDays[month-1];    //  BAD: no spaces around [] content
        }

        return {"days": days};          //  BAD: no spaces around {} content
    }

Spaces Before

Spaces are required before:

  • Blocks
  • Keywords (break, catch, class, const, continue, do, else, finally, for, function, if, let, return, switch, throw, try, var, while, with, yield)
  • Object literal property values

For example, this is good:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    function getDaysInMonth( month, year ) {

        var monthDays,
            days;

        monthDays = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];

        if ( month === 2 ) {

            // february, taking leap years into account
            if ( year % 400 === 0 ) {
                days = 29;
            } else if ( ( year % 4 === 0 ) && ( year % 100 !== 0 ) ) {
                days = 29;
            } else {
                days = 28;
            }
        } else {

            //  all other months
            days = monthDays[ month - 1 ];
        }

        return { "days": days };
    }

and this is bad:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    function getDaysInMonth( month, year ){

        var monthDays,
            days;

        monthDays = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];

        if ( month === 2 ){                                 //  BAD: no space before block

            // february, taking leap years into account
            if ( year % 400 === 0 ){
                days = 29;
            }else if ( ( year % 4 === 0 ) && ( year % 100 !== 0 ) ){
                days = 29;
            }else{
                days = 28;
            }
        }else{                                              //  BAD: no space before "else" keyword

            //  all other months
            days = monthDays[ month - 1 ];
        }

        return{ "days":days };                              //  BAD: no space before object literal property value
    }

Spaces After

Spaces are required after:

  • Commas
  • Semicolons
  • Keywords (case, catch, do, else, finally, for, if, return, switch, throw, try, while, with)
  • Unary word operators (delete, new, typeof, void, yield)
  • Start of comments

For example, this is good:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    function ApplyConfigToWidgets() {

        var config,
            ids,
            i;

        config = gConfig;
        ids = [];

        if ( config && config.widgets ) {

            //  load proper content into each widget, via ajax
            for ( i = 0; i < config.widgets.length; i++ ) {

                //  define a closure to isolate state instance
                ( function( state ) {

                    var method,
                        code,
                        config,
                        $placeholder,
                        start,
                        stop;

                    if ( "swatWidgetType" in state ) {

                        //  extract information from state
                        code = state.swatWidgetType.replace( /^sw-/, "" );
                        method = state.swatWidgetType.replace( /^sw-dashboard/, "" );
                        config = state.swatConfig;

                        //  locate placeholder
                        $placeholder = $( "#" + ids[ i ] );

                        //  load widget content via ajax
                        LoadWidgetViaAjax( {
                            "$container": $placeholder,
                            "code": code,
                            "method": method,
                            "config": config
                        } );
                    }
                } )( config.widgets[ i ] );
            }
        }
    }

and this is bad:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
    function ApplyConfigToWidgets() {

        var config,ids,i;                                       //  BAD: no space after commas

        config = gConfig;
        ids = [];

        if( config && config.widgets ) {

            //load proper content into each widget, via ajax
            for( i = 0;i < config.widgets.length;i++ ) {        //  BAD: no space after semicolons

                //define a closure to isolate state instance
                ( function( state ) {

                    var method,code,config,$placeholder,start,stop;

                    if( "swatWidgetType" in state ) {           //  BAD: no space after keyword

                        //extract information from state
                        code = state.swatWidgetType.replace( /^sw-/,"" );
                        method = state.swatWidgetType.replace( /^sw-dashboard/,"" );
                        config = state.swatConfig;

                        //locate placeholder                    //  BAD: no space after start of comment
                        $placeholder = $( "#" + ids[ i ] );

                        //load widget content via ajax
                        LoadWidgetViaAjax( {
                            "$container": $placeholder,
                            "code": code,
                            "method": method,
                            "config": config
                        } );
                    }
                } )( config.widgets[ i ] );
            }
        }
    }

Spaces Not Allowed

Spaces are not allowed:

  • Before commas
  • Before semicolons
  • Before another space (i.e. multiple spaces)
  • Before the opening parenthesis of a function (definition or call)
  • After unary non-word operators (-, +, --, ++, !, !!)

For example, this is good:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    function ApplyConfigToWidgets() {

        var config,
            ids,
            i;

        config = gConfig;
        ids = [];

        if ( config && config.widgets ) {

            //  load proper content into each widget, via ajax
            for ( i = 0; i < config.widgets.length; ++i ) {

                //  define a closure to isolate state instance
                ( function( state ) {

                    var method,
                        code,
                        config,
                        $placeholder,
                        start,
                        stop;

                    if ( "swatWidgetType" in state ) {

                        //  extract information from state
                        code = state.swatWidgetType.replace( /^sw-/, "" );
                        method = state.swatWidgetType.replace( /^sw-dashboard/, "" );
                        config = state.swatConfig;

                        //  locate placeholder
                        $placeholder = $( "#" + ids[ i ] );

                        //  load widget content via ajax
                        LoadWidgetViaAjax( {
                            "$container": $placeholder,
                            "code": code,
                            "method": method,
                            "config": config
                        } );
                    }
                } )( config.widgets[ i ] );
            }
        }
    }

and this is bad:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    function ApplyConfigToWidgets () {

        var config ,                                            //  BAD: space before comma
            ids ,
            i ;                                                 //  BAD: space before semicolon

        config = gConfig ;
        ids    = [] ;                                           //  BAD: space before space (multiple spaces)

        if ( config && config.widgets ) {

            //  load proper content into each widget , via ajax
            for ( i = 0 ; i < config.widgets.length ; ++ i ) {  //  BAD: space after unary non-word operator (++)

                //  define a closure to isolate state instance
                ( function ( state ) {                          //  BAD: space before function ()s

                    var method ,
                        code ,
                        config ,
                        $placeholder ,
                        start ,
                        stop ;

                    if ( "swatWidgetType" in state ) {

                        //  extract information from state
                        code = state.swatWidgetType.replace ( /^sw-/ , "" ) ;
                        method = state.swatWidgetType.replace ( /^sw-dashboard/ , "" ) ;
                        config = state.swatConfig ;

                        //  locate placeholder
                        $placeholder = $( "#" + ids[ i ] ) ;

                        //  load widget content via ajax
                        LoadWidgetViaAjax ( {
                            "$container": $placeholder ,
                            "code":       code ,
                            "method":     method ,
                            "config":     config
                        } ) ;
                    }
                } ) ( config.widgets[ i ] ) ;
            }
        }
    }

Blank Lines

Blank lines are required:

  • After a `var` statement
  • Before a comment
  • At the end of the file

Blank lines are not allowed:

  • After a comment
  • After a blank line (e.g. multiple blank lines)

For example, this is good:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    function getDaysInMonth( month, year ) {

        var monthDays,
            days;

        monthDays = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];

        if ( month === 2 ) {

            // february, taking leap years into account
            if ( year % 400 === 0 ) {
                days = 29;
            } else if ( ( year % 4 === 0 ) && ( year % 100 !== 0 ) ) {
                days = 29;
            } else {
                days = 28;
            }
        } else {

            //  all other months
            days = monthDays[ month - 1 ];
        }

        return { "days": days };
    }

and this is bad:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    function getDaysInMonth( month, year ) {

        var monthDays,
            days;                                           //  BAD: missing blank line after `var` statement
        monthDays = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];

        if ( month === 2 ) {
            // february, taking leap years into account     //  BAD: missing blank line before comment
                                                            //  BAD: blank line after comment
            if ( year % 400 === 0 ) {
                days = 29;
            } else if ( ( year % 4 === 0 ) && ( year % 100 !== 0 ) ) {
                days = 29;
            } else {
                days = 28;
            }
        } else {
            //  all other months

            days = monthDays[ month - 1 ];
        }

                                                            //  BAD: multiple blank lines

        return { "days": days };
    }                                                       //  BAD: missing blank line at end of file

Other

Other whitespace guidelines for JavaScript are:

  • Use consistent line breaks
  • Avoid irregular whitespace characters (e.g. zero width space, non-breaking space, vertical tab, etc.)

By definition, line breaks and irregular whitespace characters are invisible, so we can't provide a meaningful visual example here.

Next time

Function conventions.

Source: http://www.finitewisdom.com/people/joshua-...