0

I have the following config javascript, where i can hardcode the selectors divs etc and set few attributes so it can be invoked by other functions to provide the needed values. I don't want to create seperate instance everytime i invoke ex. config = new Config() which is not good. So i have changed the code in the form of javascript closures, is that will have only one instance no matter how many times it is created?

Config = function() {
    /**
     * Ids to external objects.
     * @public
     * @type object
     */
    this.ids = {
        objec1: "whiteboard",
        text1: "dialogInputText",
        image1: "dialogInputImage",
        icons: "dialogIcons",
        size: "dialogResize"
    };
    /**
     * Paper Type
     * @public
     * @type property
     */
    this.types = {
            store: "TSC",


            document: "Document"
        }
}

Convert to closure

Config = (function(){
result = {        /**
         * Ids to external objects.
         * @public
         * @type object
         */
        ids: {
            objec1: "whiteboard",
            text1: "dialogInputText",
            image1: "dialogInputImage",
            icons: "dialogIcons",
            size: "dialogResize"
        },
        /**
         * Paper Type
         * @public
         * @type property
         */
        types: {
                store: "TSC", 
                document: "Document"
            }



})()
user1595858
  • 3,700
  • 15
  • 66
  • 109
  • 3
    It seems like in your case you could also just write `Config = { ids: {...}, type: {...}};` – basilikum Jun 26 '13 at 19:12
  • Why are you using functions at all? As mentioned above, just define a data structure. – user229044 Jun 26 '13 at 19:17
  • Side note - singletons are poisonous. Having global state will make your life really hard and testing a pain. It's very hard to test code that relies on global code that is hiding somewhere. Instead, pass that object to the function doing the bootstrapping. (Remember, [singletons are pathological liars](http://misko.hevery.com/2008/08/17/singletons-are-pathological-liars/)) – Benjamin Gruenbaum Jun 26 '13 at 19:20

2 Answers2

1

I like doing something like this...

function MySingletonClass() {

  if ( arguments.callee._singletonInstance )
      return arguments.callee._singletonInstance;
  arguments.callee._singletonInstance = this;
   this.Foo = function() {
       // ...
   }
}

var a = new MySingletonClass()
var b = MySingletonClass()
Print( a === b ); // prints: true

I think it should be easy to implement and test.

From here... https://code.google.com/p/jslibs/wiki/JavascriptTips#Singleton_pattern

Hope this helps.

recneps
  • 1,285
  • 5
  • 16
  • 27
1

You haven't actually created a closure there, you are just creating a function and executing it in-situ. Config is storing the return from that function.

What you are looking for is to have a somewhat more complex object. You could do something like this:

Config = (function() {
    var ids = {
        objec1: "whiteboard",
        text1: "dialogInputText",
        image1: "dialogInputImage",
        icons: "dialogIcons",
        size: "dialogResize"
        },
        types = {
            store: "TSC",
            document: "Document"
        }
     return {
         getIDs: function (id) {
             return ids[id];
         },
         getTypes: function (type) {
             return types[type];
         }
     }
}());

Here, getIDs and getTypes are accessing variables that cannot be modified or seen from outside, and are actually the only available methods in Config.

(function(){}()) is roughly equivalent to function name(){} name(), Although the syntax is confusing, what you are doing is actually declaring an anonymous (unnamed) function and executing it as soon as it is declared (which you couldn't do in another way, since it hasn't got any name). The result from evaluating that expression is the result of executing that function. Note however that the first expression won't introduce any new variables in the larger scope (and this is the primary reason why this construct is used), whereas the other declaration will.

Ok, so if you want to store objects instead of plain data (strings or numbers), you will have to go to great lengths in order for those objects not to be modifiable. The most straightforward way IMHO would be to store object json encoded and return them decoded. If this is not nice enough, you will have to check another answers on how to "clone" a javascript object you can check this question What is the most efficient way to deep clone an object in JavaScript?

So, by using JSON the anonymous function would become something like this

(function () {
    var ids = {
       object1: '{"whiteboard":"an object\'s property"}',
       text1: '["an","array"]'
      },
     ...
return {
    getIDs: function (id) {
         return JSON.parse(ids[id]);
    },
    getTypes: function (type) {
         return JSON.parse(types[type]);
    }
}
}());

I hope this helps

Community
  • 1
  • 1
Pablo Mescher
  • 26,057
  • 6
  • 30
  • 33
  • Will it still restrict instantiation of a class to one obeject? – user1595858 Jun 26 '13 at 19:30
  • No. This will make the information contained inmutable. You can access this info from window.Config from all your js files. Just make sure you include this code first before all the scripts that depend on it. – Pablo Mescher Jun 26 '13 at 20:59
  • that means i dont have to do config = new Config(); at all – user1595858 Jun 26 '13 at 22:42
  • Nope. Just put this code as is somewhere on your javascript and it will be accessible by all the code that comes afterwards. – Pablo Mescher Jun 27 '13 at 12:37
  • what if I have types ={store :{size:'blue',length:13}} and I want to get types.store[size] – user1595858 Jun 28 '13 at 03:47
  • You can do Config.getTypes("store").size since getTypes("store") will return the store object. However, in this particular case you will be able to change its value. If you want the data to be even more safe, you can return a copy of the data stored. I will update my answer to do that – Pablo Mescher Jun 28 '13 at 18:01
  • You're wrong on the `(function name(){} name())` assertion - in a named function expression `name` is only visible _within the scope of the function_ (i.e. within the `{}` block). Unless you're on old broken versions of MSIE. Nor is this code a "function declaration". – Alnitak Jul 08 '13 at 20:49
  • @Alnitak you are right, I should have said function name() {} name() vs (function () {})(). And still, the second statement isn't exactly equivalent. I was just trying to clarify the rather obscure syntax to newcomers to JavaScript – Pablo Mescher Jul 08 '13 at 21:01
  • @PabloMescher and yet there is a significant difference, precisely because the former `function name() { ... }` will introduce `name` into the current scope, whereas `(function name() { ...})()` will not. – Alnitak Jul 08 '13 at 21:03
  • @Alnitak I understand that difference, but I believe it's not important to the point being made (that (function() {})() declares a function and executes it in situ) – Pablo Mescher Jul 08 '13 at 21:12
  • @PabloMescher then you should remove the comparison, because as written it is confusing and incorrect. – Alnitak Jul 08 '13 at 21:17
  • @Alnitak I edited my answer to be more accurate, and hopefully less confusing – Pablo Mescher Jul 09 '13 at 00:03