0

I have some functions inside of functions and I am having trouble retrieving a variable. It will be easier to show in code I want to log the var three in the testit function but not sure how to do so.

test();

function test(){
    var abc;
  function one(){
    abc = 1;
    two();
  }
  var three;
  function two(){
    console.log(abc);
    three = 2;
    testit();
  }
    one();

}

function testit(){
  console.log(three);
  two();
}
Anders Kitson
  • 1,413
  • 6
  • 38
  • 98

5 Answers5

1

to make test an object you would do the following:

function test(){
    this.abc = 0;
    this.three = 0;
    this.one();
}
test.prototype.one = function(){
    this.abc = 1;
    this.two();
}
test.prototype.two = function(){
    console.log(this.abc);
    this.three = 2;
}
test.prototype.testit = function(){
    console.log(this.three);
    this.two();
}

and run it like so:

testObj = new test();
testObj.testit();

hope this helps.

edit: BTW: if you put a call in function 'two' back to function 'testit' you'll end up with an infinite loop.

logic8
  • 874
  • 9
  • 21
1

Here's an explanation of what's happening:

When you wrap code in a function, you get what's called function scope. This means that the scope within the function belongs to the function and not to a scope above or outside of it (whichever way you want to look at it).

A closure allows an expression (typically, a function, as MDN states) to have it's own scope while sharing the scope of it's outer or higher scope.

So, let's look at an example:

// This represents the global, or window, scope.
// Analogous to window.outer_var.
var outer_var = 'outer var';

function outer_func() {
    // New scope! Local only to outer_func and those
    // expressions (functions) *enclosed* by 
    // `outer_func(){...}, e.g. inner_func(){...}.
    var inner_var = 'inner var';

    // Only outer_func() or inner-enclosed (to
    // inner_func()'s definition) functions can
    // access inner_func().
    function inner_func() {
        // Another new scope! Can access inner_var
        // and inner_func_var (below). outer_func()
        // canNOT access inner_func_var, though.
        var inner_func_var = 'inner func var';
    }
}

outer_func(); // Of course, it's in scope and accessible.
inner_func(); // This will cause ReferenceError: inner_func is not defined error.

Simply as it is (no wrapping context, with a closure), var outer_var is created with the global or window scope. It may be accessed in all of the following:

  1. console(window.outer_var);
  2. function outer_func() {console.log(outer_var);}
  3. function inner_func() {console.log(outer_var);} No matter where inner_func's defined.

Here, #2/3 are analogous to:

  1. function outer_func() {console.log(window.outer_var);}
  2. function inner_func() {console.log(window.outer_var);}

Or global this:

  1. function outer_func() {console.log(this.outer_var);}
  2. function inner_func() {console.log(this.outer_var);}

Now, inner_var is accessible from the following:

  1. function outer_func() {console.log(inner_var);}
  2. function inner_func() {console.log(outer_var);} Only from within outer_func().

inner_func() may also only be accessed within outer_func(), because it belongs to the outer_func() scope, and thus is not visible/accessible outside of outer_func()*.

Lastly, inner_func_var is only accessible by:

  1. function inner_func() {console.log(inner_func_var);} Only within outer_func().

To access your three variable, you have three choices:

  1. Make three globally accessible (globals are generally discouraged as they may easily introduce difficult to resolve bugs when one is overwritten by some other code).
  2. Return three from your test() function. In this case the value is accessed, not the actual variable within the function.
  3. Create a property as @logic8 demonstrates, so it may be accessed as a property of an object.

* This isn't entirely true. outer_func() could export a reference to the function out of scope with return inner_func;. This is a more advanced concept, though, and won't be addressed here in depth. Here is an example.

Jared Farrish
  • 48,585
  • 17
  • 95
  • 104
0

You have to put it in a global to do so:

test();
var three = false;

function test(){
[..]
}

function testit(){
  console.log(three);
  two();
}
Rene Pot
  • 24,681
  • 7
  • 68
  • 92
  • Please don't do this. Use a closure – Codeman Jul 31 '14 at 22:12
  • Also, this doesn't create a global. Globals are created when variables are declared without using a var keyword. – Codeman Jul 31 '14 at 22:21
  • @Pheonixblade9 - If `var` is used in the global scope, [it's accessible as demonstrated](http://jsfiddle.net/2Qv6V/). However, I would discourage using globally-scoped variables wherever possible. – Jared Farrish Jul 31 '14 at 22:46
0

when you declare a variable with var it becomes local to that scope. If you want to access three in both functions, you can either declare it without var (making it global - generally frowned upon for good reasons) or declare it outside of the two functions: var three;

Mike Bell
  • 1,356
  • 11
  • 9
0

The correct way to do this is by using the closure pattern in javascript. This wraps your javascript class in its own function so anything you declare within that file is only local to your code.

Using jQuery, this is easily accomplished like so:

(function($){
  //your code goes here
})(jQuery);

People typically do it this way so their javascript only executes when the page is ready:

$(document).ready(function(){
    //your code goes here
});

It's a bit more complicated without jQuery if you want to execute your code when the document is ready:

document.addEventListener('DOMContentLoaded', function(){
   console.log('document is ready. I can sleep now'); 
 });

With your code, it would look something like this:

$(document).ready(function(){
    var test = function(){
        //test code here
    };

    var one = function(){
        //one code here
    };

    var two = function(){
        //two code here
    };

    var three = function(){
        //three code here
    };

    var testIt = function(){
        //test code here
    };
});

This way, you can safely access all of your functions from the others without polluting the global namespace.

Community
  • 1
  • 1
Codeman
  • 12,157
  • 10
  • 53
  • 91
  • While this is a fine answer, you're making a lot of assumptions about what OP "wants to do" (and that he's using jQuery). Without seeing any "real code" (the code posted is clearly a toy), it's a bit premature to discuss design patterns. :P – Mike Bell Jul 31 '14 at 22:28
  • Right. I assumed OP was new to JS, so I tried to give a bit of guidance - I tend to go overboard on my answers :) What would you change/remove? I'm happy to do it – Codeman Jul 31 '14 at 22:29
  • @MikeBell also, I included the non-jquery version (though admittedly it doesn't work in IE<8 :P ) but thought it'd be good to include the jQuery version. – Codeman Jul 31 '14 at 22:31
  • You make it sound as if jQuery is required (or `onDOMReady`) to have a closure. The OP doesn't indicate anything about needing a specific event handler, and your answer should not confuse the two. – Jared Farrish Jul 31 '14 at 22:41
  • Yea I feel like everyone's completely conflating this question. It's a very simple question with an incredibly simple answer: if you want to access a variable, it has to be in scope. If you want to access a variable in two different places, the variable needs to be in scope of both of those places. Pretty standard stuff. – Mike Bell Aug 01 '14 at 04:21