0

I have a feeling I'm missing something obvious. I'm returning a variable from my javascript module, but it keeps coming back undefined.

Here's the module:

var MyNs = MyNs || {}; 
MyNs.Global = function () {
   var privateTestVar;
   var init = function () {
       if (privateTestVar == null ) {
           privateTestVar = "this is a test" ;
           console.log( 'Init: ' + privateTestVar);
       }
   };

   var Public = {
       init: init,
       TestVar: privateTestVar
   }

   return Public;
} ();

Here's the call:

MyNs.Global.init();console.log( 'Called: ' +MyNs.Global.TestVar);

The console.log in the init function works fine and returns the value, but the other console log returns undefined. I'm totally missing it. Any help would be appreciated.

Update: I've change the code a bit, to this:

    var privateTestVar = function () { return 'Test!'; }

var Public = {
    TestVar: privateTestVar
}

And variations of that, but it returns this exact text to the console: "function () { return 'Test!'; }"

0

4 Answers 4

3

At the time that Public is assigned here:

var Public = {
    init: init,
    TestVar: privateTestVar
}

privateTestVar is still undefined (because init() hasn't been run yet) so the TestVar property is initialized to the value of privateTestVar which is undefined.

The TestVar property gets assigned the value of privateTestVar. If it's initially undefined (which it is in this case), it will stay that way until you assign something different to the TestVar property. I won't automatically inherit future values of privateTestVar which is perhaps what you were expecting. Javascript does not have a way of specifying that one variable will always contain whatever is assigned to another variable. privateTestVar and the TestVar` property each have their own value. Assigning something to one variable does not affect the other.

Sign up to request clarification or add additional context in comments.

5 Comments

Actually, I call the "init" function first, which should assign a value to privateTestVar, making it suitable for returning.
@JoshC - where is init() called? It's not called in your example before TestVar is assigned the value of privateTestVar so that's why TestVar contains undefined. init() would have to be called BEFORE the TestVar property was created and initialized.
It's called like so: MyNs.Global.init();console.log('Called: ' +MyNs.Global.TestVar);
@JoshC - please read what I've written several times. You're calling it too late. The value of TestVar is already set in the declaration of Public when you then call init(). So you calling init() does not affect the value of the TestVar property in any way.
Okay...I see what you mean...sorry...I read right past it a few times. I wan't quite groking that by returning public, that means it's called first.
1

I'd suggest making a private variable really a private one, using getters instead. This will work correctly:

var Public = {
    init: init,
    getVar: function() { return privateTestVar; }
}

MyNs.Global.init();console.log( 'Called: ' +MyNs.Global.getVar());

2 Comments

Okay....this is really odd...now it returns the actual text in the function. The console reads like this: "Called: function () { return privateTestVar; }"
It means you're trying to log the function itself, not its result. Don't forget the parenthesis (Global.getVar()).
0

Issue is as stated by @jfriend00. Change the code to

var init = function () {
    if (privateTestVar == null ) {
        privateTestVar = "this is a test" ;
        Public.TestVar = privateTestVar;
        console.log( 'Init: ' + privateTestVar);
    }
};

I didn't test this out but theoretically it should work.

1 Comment

Use raina77ow's suggestion. It's better.
0

I think this is the structure you are looking for:

function PrivateFunc(private, public){
  this.privateVar = private;
  this.publicVar = public;
}
function PublicFun(public){
  this.publicVar = public;
  if(this.publicVar == null)this.publicVar = 'This is a public variable.';
  this.PrivateFun = function(private){
    return new PrivateFunc(private, this.publicVar);
  }
}

var pf = new PublicFun('public variable');
var pv = pf.PrivateFun('private variable');
console.log('pf.publicVar = '+pf.publicVar);
console.log('pf.privateVar = '+pf.privateVar);
console.log('pv.publicVar = '+pv.publicVar);
console.log('pv.privateVar = '+pv.privateVar);

Notice that PrivateFunc is not PrivateFun. The real factor comes down to the key word this. this refers to the current Object as when you type this. var is only accessible inside your method. You should think of a JavaScript Object as an Associative Array. If that doesn't suit your needs try:

var jsObject = {
  publicVar: null,
  PrivateFun: function(private){
    var privateVar = private; //cannot access with dot
    return this;
  },
  PublicFun: function(public){
    this.publicVar = public;
    if(this.publicVar == null)this.publicVar = 'This is a public variable';
    return this;
  }
}

var pf = jsObject.PublicFun();
var pv = jsObject.PrivateFun('private variable');
console.log('pf.publicVar = '+pf.publicVar);
console.log('pf.privateVar = '+pf.privateVar);
console.log('pv.publicVar = '+pv.publicVar);
console.log('pv.privateVar = '+pv.privateVar+' //cannot access with dot');

Note that Object Literals are not Constructors, so you cannot make new instances. Also, in the Object Literal case, var privateVar is virtually useless, unless you don't want the privateVar returned. this must be returned in order to access jsObject, which holds the reference to publicVar.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.