Search code examples
javascriptperformancevariablesdeclarationutility

js: var declarations, loops, efficiency, utility


readability aside ... in terms of efficiency and/or functionality, i'm not clear on the difference between placing a declaration outside (my practice) or inside a loop (seen in other SO posts). or for that matter, why code declarations at all? here are some degenerate examples ... more comments below.

A1:

var x;
for (i=0; i<10; i++){
    x = i;
 }

A2:

for (i=0; i<10; i++){
    var x = i;
 }

B1:

var i;
for (i=0; i<10; i++){
 }

B2:

for (var i=0; i<10; i++){
 }

C1:

var x;
var y;

C2:

var x, y;

readability aside ... i suspect that there is no difference between B1 & B2 and between C1 & C2, but am leery of an efficiency or functional difference between A1 & A2. also, i am not sure what advantages exist for declarations at all except for using declarations in functions to eliminate(?) possible conflict with a global variable of the same name.

EDIT: added a couple semicolons

EDIT: 1st sentence clarity, changed function to functionality

EDIT: adding some code below to aid in a comment below that i made EDIT: comments

<!doctype html>
<html>
<head>
<script type='text/javascript'>
var w = (function(){  // wrapper
    alert('init');
    function p(){ // private
        alert('p');
        w.b(); //needs prefix
    }
    return{
        a: function(){ // public
            alert('a'); 
            p();
            w.b(); // needs prefix 
        },
        b: function(){ // public
            alert('b'); 
        }
    };
})(); // execute immediately
</script>
<script type="text/javascript">window.onload=w.a;</script>
</head>
<body>
sequence of alerts will be 'init' 'a' 'p' 'b'
</body>
</html>

Solution

  • Variable declarations get hoisted up to the top of the function. It won't make any difference, unless of course you're talking about declaring a variable in a new function scope.


    EDIT: Didn't notice at first, your first example didn't declare i with var. That's not good practice.


    EDIT:

    Generally it is a good idea to avoid creating global variables in order to avoid conflicts with other scripts that may be setting globals.

    Whenever you use a variable without declaring it with var, it becomes global.

    The only way a new variable scope is created in JavaScript is in the body of a function. Functions can be nested inside each other, creating a scope chain that begins with the innermost function, and ends with the global scope.

    Because of this, it is common to place all your code in a function that is invoked immediately. That way any variables you create with var won't end up as globals.

    (function() {   // <-- create a function
    
        // place your code in here
    
          // use "var" when declaring variables so they don't become global
        var name = "patrick dw";
    
        alert( name );
    
    })(); // <-- invoke the function immediately so your code runs
    

    In the preceding example, the name variable will be local to the immediately invoked function, and won't pollute the global scope.

    Because traversing the variable scope takes some resources, it is common for people to invoke that function with some arguments being passed in, like window.

    (function( window, undefined ) {
    
          // now the window object is referenced locally. Better for performance.
    
        var name = "patrick dw";
    
        alert( name );
    
    })( window ); // <-- invoke the function passing in the global "window" object
    

    Now the window object is referenced locally inside your function, so if you access some property of window, it won't have to follow the scope chain all the way outside your function.

    I also included an extra undefined parameter in the function, but didn't pass an argument to it. This is to help avoid an odd issue brought about by some bad coding practices. But that's another issue.

    Now taking that same function, if we didn't use var in declaring our name variable, it would automatically have become global. I'll update the example, and I'll add another function scope to illustrate.

    (function( window, undefined ) {
    
              // create a function 
        function some_func() {
    
            name = "patrick dw";  // didn't use "var" when declaring!!
            alert( name );
        }
    
        some_func();  // call our function
    
        alert( window.name ); // but "name" is also accessible from the global window
    
    })( window );
    
    alert( name ); // outside those functions, we're global, and again we can see that
                   //   the "name" variable is accessible
    

    So as you can see, we never declared var name, so it became an automatic global variable even though it was nested two functions deep.

    This is the source of many errors, and is the reason you need to be extra careful to use var.


    Finally, I'd note that ECMAScript 5 disallows some bad coding practices when you run your code in "strict mode";. Not many browsers implement strict mode right now, but would be helpful to test your code every so often in one that does.

    Here's a compatibility table for ECMAScript 5. Strict mode is at the bottom. You'll see that Firefox 4 supports it.

    Here's an example:

    (function( window, undefined ) {
    
        "strict mode"; // <-- use the strict mode directive
    
        name = "patrick dw";  // In Firefox 4, you should get a ReferenceError in the console
                              //   because "name" was never declared with "var"
    })( window );