netemp
netemp

Reputation: 4185

Javascript scope issue: variable not being identified

I have two functions, one function calling the other.

Below is a simple analogy I created of the structure of code which I have:

function test1(){
    alert(a);//a is not identified here even when test1() is called under test2 which has a defined in scope
    alert(b);//b is identified here
}

function test2(){
    var a       =       'a';//Defining a
    test1();//Calling test1()
}
var b   =   'b';
test2();

As per the code above, function test1() is able to identify variable b but not variable a.

My question is that why variable a is not in the scope of test1 function even when we are calling test1() inside test2() which defines variable a?

Thanks in advance.

Upvotes: 2

Views: 2073

Answers (5)

Bakudan
Bakudan

Reputation: 19482

It is a good practice to call the functions with arguments. This will make your code easily readable and maintainable. Just adding arguments to the functions make the code working:

function test1(a,b){
    alert(a);
    alert(b);
}

function test2(b){
    var a = 'a';
    test1(a,b);
}
var b = 'b';
test2(b);

If you don`t want to use arguments in the function declarations, a solutions is to use the arguments object inside the code:

function test1(){
    alert(arguments[0]);
    alert(arguments[1]);
}

function test2(){
    var a = 'a';
    test1(a,arguments[0]);
}
var b = 'b';
test2(b);

If you want you can make the arguments with default values. Since in JavaScript you can`t do it in the function argument list, it is done in the body of the function:

function test1(a,b){
    a = a || 'a';
    b = b || 'b';
    alert(a);
    alert(b);
}
function test2(b){
    var a = 'a';
    test1(a);//here b is not passed to the function and b will get the default value
}
var b = 'some new string for b';
test2(b);

Live on jsfiddle

Upvotes: 2

IanR
IanR

Reputation: 4773

JavaScript has 'function scope' which means that anything defined in a function is not visible outside of the function. So variable 'a' is not visible outside of test2. However, variable 'b' is a global variable so it is visible in every scope.

Function scope also means that inner functions get access to things defined in the outer function but that doesn't come in to play here...test1 is called from within test2 but it's not an inner function of test2. To see this in action you'd need to define the body of the test1 function within test2...

function test2(){
    var a       =       'a';//Defining a
    test1();//Calling test1()

    function test1(){
        alert(a);//a is identified here because of function scope
        alert(b);//b is identified here because it's global
    }
}

Upvotes: 2

user123444555621
user123444555621

Reputation: 152956

Functions remember their scope chain at the time they're being created, not at the time they're called.

Note that b gets "hoisted", so your code actually does this:

var b; // push b on scope chain

function test1(){ // store scope chain [b]
    alert(a);
    alert(b);
}

function test2(){ // store scope chain [b]
    var a; // push a on scope chain
    a = 'a';
    test1(); //Calling test1() which still has scope chain [b], not [b,a]
}
b   =   'b';
test2();

Upvotes: 3

AmGates
AmGates

Reputation: 2123

According to your functions you have declared and defined the variable "a" within the function "test2()" so the scope of the variable "a" is restricted within that function itself and accessing the variable will return "undefined". But it is not in the case of the variable "b" which is declared and defined globally, So it can be accessed any where in the script part.

hope this helps you.

Upvotes: 0

Jayantha Lal Sirisena
Jayantha Lal Sirisena

Reputation: 21366

your expectation is wrong about the scope of the variables,

according to your code b is a global variable to 2 functions and a is in the scope of test2 function only because it is defined withing test2, If you want something like you expected you can define test1 function in test2 scope like this,

function test2(){
    var a       =       'a';
    test1();
  function test1(){
      alert(a);
      alert(b);
   }
}
var b   =   'b';
test2();

Upvotes: 3

Related Questions