2

I am trying to learn how to create JavaScript class in another .js file and access it from anywhere else. I have read a few examples, but can't seem to understand it completely.

For example, how do I access the following:

//code in file2.js
getterTest = (function() {
  var _x = 15;

  return {
    doSomething: function() {
      _x += 5;
    },

    get x() {
      return _x;
    }
  }
});

//code in file1.js
console.log(getterTest._x); //undefined
console.log(getterTest.x); //should give 15
getterTest.doSomething();
console.log(getterTest.x); //should give 20

But it all gives undefined and the .doSomething method gives not a function.

I will go home now and read more about closure as @Liam suggested and will see what is going on tomorrow.

Liam
  • 27,717
  • 28
  • 128
  • 190
Igor
  • 45
  • 7
  • 1
    `getterTest` is a function, you'd have to call it first. Did you mean to use an IIFE? – elclanrs Mar 31 '16 at 15:50
  • This isn't a singleton. It's a [closure](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work). – Liam Mar 31 '16 at 15:50
  • `console.log(getterTest().x);` – Liam Mar 31 '16 at 15:54
  • @Liam hmm, maybe I am in a mistake. I am going to read about closure. – Igor Mar 31 '16 at 15:55
  • @elclanrs I am not familiar with immediately-invoked function expression, but I will - this should give me an idea. – Igor Mar 31 '16 at 15:56
  • It's pretty much impossible to create a [singleton pattern](https://en.wikipedia.org/wiki/Singleton_pattern) in Javascript. There is no common context. – Liam Mar 31 '16 at 15:57
  • @Liam thanks for the missed ( ), now I get the 15, but the .doSomething still does not work. – Igor Mar 31 '16 at 15:57
  • add the `()` again to call the `getterTest` function `getterTest().doSomthing()` – M B Mar 31 '16 at 15:58
  • @Liam ... not sure, but still, can you recommend any readings on how to achieve public accessible class methods without new Class()? – Igor Mar 31 '16 at 15:59
  • @MB did so, it got to it, but says 15 instead of 20 :( – Igor Mar 31 '16 at 16:03
  • created a fiddle for this,try here pelase https://jsfiddle.net/mp9tgq89/ – Well Wisher Mar 31 '16 at 16:10
  • @IgorGeorgiev see answer – M B Mar 31 '16 at 16:10
  • @Wellwisher doesn't print anything on fiddle... – Igor Mar 31 '16 at 16:13
  • @MB Cheers, will try it tomorrow, cause I am going home – Igor Mar 31 '16 at 16:13
  • Don't edit the question to say it's solved. Marking an answer is enough. The question needs to remain to help others who may have a similar problem – Liam Apr 01 '16 at 08:14
  • @Liam sorry, did not know that. Should I edit it back, or should I have that in mind for the next time? – Igor Apr 01 '16 at 12:07
  • I've already fixed @Igor. Users with higher rep can edit other user posts. Just bear it in mind for next time :) – Liam Apr 01 '16 at 12:27

3 Answers3

2

Ok lets break this down

getterTest = (function() {});

getterTest is a function pointer. i.e. it is a variable that holds the un-envoked function.

If I do:

getterTest = (function() {});
getterTest();

I invoke the function.

If I do:

getterTest = (function() {});
var result = getterTest();

result contains the function returned from the getterTest function, i.e. an object ({}) that contains a function and a gettable x property

result = {
    doSomething: function() {
       _x += 5;
    },

    get x() {
        return _x;
    }
}

so I could do:

getterTest = (function() {});
var result = getterTest();
result.x;

TL;DR

Really though; what you want is for getterTest to work like this:

getterTest = function() {
var _x = 15;

return {
    doSomething: function() {
       _x += 5;
    },

    get x() {
        return _x;
    }
}
}();
//invoke the function and store this in your variable by adding () above    

//code in file1.js
//console.log(getterTest._x);         //this is private so can't be accessed (you can only access things that are returned)
console.log(getterTest.x);         //should give 15
getterTest.doSomething();
console.log(getterTest.x);        //should give 20

Fiddle

You cannot access _x outside of the closure, because it's scope is the function. This is , essentially, the point of closures. To keep things in scopes and to keep the "global context" clean.


FYI

You might notice I kinda use "function" and "object" interchangeably in the above. People not used to Javascript find this odd but there is a good reason. In Javascript a function is an object o_O

Again this is one of the principals of what your trying to achieve here. It's all basically about encapsulation

Liam
  • 27,717
  • 28
  • 128
  • 190
  • That is very interesting :) I am used to code in AS3, and recently started with JS and all seems like a mess to me :D – Igor Apr 01 '16 at 07:58
  • JS is not a compiled language. It's built to be very flexible. This results in some weirdness if your not used to it. It is now [pretty much the most used language](http://stackoverflow.com/research/developer-survey-2016#technology) so get used to it :D – Liam Apr 01 '16 at 08:11
  • I am using it now, so I have to :D – Igor Apr 01 '16 at 12:08
0

please do as,

//code in file2.js
getterTest = (function() {
    var _x = 15;
    return {
        doSomething: function() {
           _x += 5;
        },

        get x() {
            return _x;
        }
    }
}()); // added '()'


//code in file1.js
console.log(getterTest._x);         //undefined
console.log(getterTest.x);         //15
getterTest.doSomething();
console.log(getterTest.x); 
Igor
  • 45
  • 7
Well Wisher
  • 1,825
  • 1
  • 15
  • 20
-1

you need to instantiate the class and then call the functions.

var g = getterTest(); 
console.log(g.x);         //15
g.doSomething();
console.log(g.x); //20

If you call getterTest() on each call, it will always get a new version of the class

console.log(getterTest().x);         //15
getterTest().doSomething();
console.log(getterTest().x); //15

I know this is not ideal for you. But this is the correct way to call the functions in file2.js Other choice is to rewrite file2.js
Good luck!

M B
  • 2,326
  • 24
  • 33
  • This is not a class and does not need to be instantiated and calling `new` on it will not do what you think. –  Mar 31 '16 at 16:11
  • @torazaburo see fix. removed the `new` keyword – M B Mar 31 '16 at 16:19