3

I namespace my models and a single controller like this:

var MC = {};

and then added properties as needed.

For example, the code that initializes all my models looks like this:

MC.initAll = function() {

    MC.MASettings.init();
    MC.MATweet.init();

    MC.MUserTry.init();
    MC.MUserNew.init();
    MC.MUserExist.init();

    Su.UserOut.init();
    Su.Media.init();
}

I plan on changing this to a loop...just loop through MC, and if init() exists execute it.

The only thing that bothers me about this architecture is there is no privacy or encapsulation in the traditional sense that everything is public.

Also, I don't instantiate my models, I just call them as functions, but this is pretty much the same as instantiation in .js.

Is there a simple way to add privacy to my models and still have them accessible as properties in an object.

Just for an example here is my simplest model :

MC.MUserTry = {
    init: function() {
        document.getElementById( 'ut_but' ).addEventListener( "click", function( ) {
            MC.Controller( MC.o_p( 'MUserTry' ) );
        }, false );
    },
    pre : function( o_p ) {
        o_p.page.email = document.getElementById( 'ut_but' ).getAttribute( 'data-email' );
        return o_p; 
    },
    post : function( o_p ) {
        sLocal( o_p.server.hash, o_p.server.privacy, o_p.server.name, o_p.server.picture, 'ma' );
        vStateUpdate( o_p.server.name, o_p.server.picture, o_p.server.privacy );
        vTPane( o_p.server.tweets ); vBPane( o_p.server.bookmarks ); 
        vFlipP( 'ma' ); 
    }
};

pre() runs before an ajax call, post() after, and init() is called via an onload event or similar.

Here is the controller that actually implements this.

MC.Controller = function( o_p ) {

   console.log( 'o_p = ' + o_p.model );

   var t1, t2, t3, t4, 
       i1, i2, i3, i4,
       o_p_string_send;

    if( SU.get('debug') ) {
        t1 = new Date().getTime();
    }

    o_p = MC[ o_p.model ].pre( o_p );  

    if ( o_p.result !== 'complete' ) {
        o_p_string_send = JSON.stringify( o_p );

        if( SU.get('debug') ) {
            t2 = new Date().getTime();
            console.log( '---------------Server Send: \n ' + o_p_string_send );
        } 

        cMachine( 'pipe=' + o_p_string_send , function( o_p_string_receive ) {

            if( SU.get('debug') ) { 
                console.log( '---------------Server Receive: \n ' + o_p_string_receive ); 
                t3 = new Date().getTime();
            }

            o_p.server = JSON.parse( o_p_string_receive );

            MC[ o_p.model ].post( o_p );

            if( SU.get('debug') ) {
                t4 = new Date().getTime(); i1 = t2-t1 ; i2 = t3-t2 ; i3 = t4-t3; i4 = o_p.server.time;
                console.log( '---------------Time: \n Pre | Transit | Post | Server = ', i1, ' | ', i2, ' | ', i3,' | ', i4 );  
            }

        } );
    }
};

I would like to add privacy. How do I do this and still keep my models accessible as object properties?

Related

How to create global, instance based objects from local scope?

Community
  • 1
  • 1

2 Answers2

2

you can do this with closures.

var MyNamespace = {};
MyNamespace.MyClass = (function() {
    function privateMethod() {
        // ...
    }

    function publicMethod() {
        // can call privateMethod() from in here
    }

    return ({
        publicMethod: publicMethod
    });
}());

This will create an object called MyNamespace.MyClass with one private method and one public method. In your case you probably want to do this for each model class. Have their init methods be public and hide their other methods.

Dan O
  • 6,022
  • 2
  • 32
  • 50
  • `MyNamespace.MyClass.publicMethod();` – Dan O Aug 03 '12 at 23:31
  • `MyClass` will get assigned the object with the `publicMethod` property. – Bergi Aug 03 '12 at 23:32
  • If you're running this code only once at startup, then no, internal functions won't be created multiple times. How could they? This code gets run once, `MyNamespace.MyClass` is given the return value of an anonymous function (that return value is just an object with only one property: 'publicMethod'), and that's it. – Dan O Aug 03 '12 at 23:49
1

Is there a simple way to add privacy to my models and still have them accessible as properties in an object?

Obviously, you then will need to make the whole object private. And yes, that will work as any other privacy in JavaScript, too - a closure.

Have a look at the module pattern (there are many tutorials out on the web about this).

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • A closure *is* a function. It just has the benefit of exporting an interface, which you probably will need. – Bergi Aug 03 '12 at 23:24
  • It only needs to be public to the part that calls it, in your case seemingly the `Controller`. If both are defined in the same scope, they still do not need to be global. – Bergi Aug 03 '12 at 23:31
  • 1
    No. [closures](http://stackoverflow.com/q/111102/1048572) do "*export*" (a) function(s) to be public, but still having access to the inner "private" variables. – Bergi Aug 03 '12 at 23:41
  • 1
    Yes. That method, which is now public accessible, was declared in a scope where it can reference "private" things that are unavailable from outside. – Bergi Aug 03 '12 at 23:47
  • What do you mean by "plain function"? You will not be able to access variables declared in its scope from outside. And they usually will be garbage-collected after the function execution finishes. – Bergi Aug 03 '12 at 23:54
  • The module pattern is just a closure which is just a function. And the rules are the same for all of them. – Bergi Aug 03 '12 at 23:57
  • @some_guy: An IEFE (as in the module pattern) builds a closure as well. – Bergi Mar 20 '13 at 15:11