Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No need to define a variable twice

If a variable could be defined in a function, even if no value is assigned, it becomes a local variable

so, is testB() better programming?

var test = 'SNAP!'
function testA(boolean) {
    if (boolean) var test = 'OK';
    else var test = null;
    alert(test);
}
function testB(boolean) {
    if (boolean) var test = 'OK';
    alert(test);
}
testA(true); // 'OK'
testB(true); // 'OK'
testA(false); // null
testB(false); // undefined, no error

In my specific case test's global value ('SNAP!') is neither expected nor required.

like image 409
Carlos Gil Avatar asked Oct 19 '10 23:10

Carlos Gil


2 Answers

You can't declare variables conditionally.

Why?

The variable instantiation process occurs before the actual code execution, at the time the function is executed, those variables will be already bound to the local scope, for example:

function foo () {
  if (false) {
    var test = 'foo'; // never executed
  }
  return test;
}
foo(); // undefined

When the function is about to be executed, identifiers of formal parameters, identifiers from variable declarations, and identifiers from function declarations within the function's body are bound to the local variable environment.

Variables are initialized with undefined.

Also, identifiers in the local scope shadow the others with the same name, higher in the scope chain, for example:

var test = 'global';
function bar () {
  alert(test); // undefined, not "global", the local variable already declared
  var test = 'xxx';
}
bar();

If the test variable were not declared anywhere, a ReferenceError will be thrown:

function foo () {
  return test;
}

try {
  foo(); // ReferenceError!!
} catch (e) {
  alert(e);
}

That's one of the reasons about why for example, JSLint recommends only one var statement at the top of functions, because for example, the first snippet, will actually resemble this when executed:

function foo () {
  var test; // var statement was "hoisted"
  if (false) {
    test = 'foo'; // never executed
  }
  return test;
}
foo(); // undefined

Another reason is because blocks don't introduce a new lexical scope, only functions do it, so having a var statement within a look might make you think that the life of the variable is constrained to that block only, but that's not the case.

Nested function declarations will have a similar behavior of hoisting, they will be declared before the code execution, but they are initialized in that moment also:

function foo () {
  return typeof bar;
  // unreachable code:
  function bar() {
    //..
  }
}
foo(); // "function"
like image 128
Christian C. Salvadó Avatar answered Oct 20 '22 00:10

Christian C. Salvadó


If the variable does not need to be manipulated by any other functions, keep the variable inside a function with var foo;.

Otherwise, if it does need to be accessed and read in multiple scopes, keep it outside. But remember that when you keep it outside, it becomes global. That is, unless you wrap everything in a self executing function, which is the best way:

(function() {
   var president='bush';

   function blah() {
     president='reagan';
   }

   function meh() {
     president= 'carter';
   }

   document.getElementById('reagan').onclick=blah;
   document.getElementById('carter').onclick=meh;


})();

alert( president ) // undefined

The above is perfect for a variable accessed by functions defined inside of that scope. Since there are 2 elements i click to set the president, it makes sense to define it outside both functions because they set the same variable.

So, If you are not dealing with multiple functions changing the exact same variable, keep them local to the function.

like image 42
meder omuraliev Avatar answered Oct 19 '22 23:10

meder omuraliev