2
\$\begingroup\$

I have done the following code for testing a web-service.

Is my style correct for using OOP in JavaScript?

<script>
    function Ajax() {
        var Base = {
                createAjaxInstance: function() {
                    var ajax = null;

                    try {
                        ajax = new ActiveXObject( "Msxml2.XMLHTTP" );
                    }
                    catch ( exception ) {
                        try {
                            console.log( "Can't create `Msxml2.XMLHTTP` object for " + navigator.userAgent + "." );
                            ajax = new ActiveXObject( "Microsoft.XMLHTTP" );
                        }
                        catch ( exception ) {
                            console.log( "Can't create `Microsoft.XMLHTTP` object for " + navigator.userAgent + "." );
                            ajax = false;
                        }
                    }

                    if ( !ajax && typeof XMLHttpRequest != "undefined" ) ajax = new XMLHttpRequest();
                    else console.error( "Failed to create any `XmlHttp` instance!" );
                    return ajax;
                },
                getAjaxInstance: function() {
                    var ajax = this.createAjaxInstance();
                    return ajax;
                }
        };

        var instance = Base.getAjaxInstance();
        return instance;
    }

    function UI() {
        var Base = {
            Controllers: {
                addContainer: function( element, id, inputHtml ) {
                    var container = document.createElement( element );
                    container.id = id;
                    container.innerHTML = inputHtml;
                    document.body.appendChild( container );
                },
                addControl: function( element, id, type, value, eventName, eventBehaviour ) {
                    var control = document.createElement( element );
                    control.id = id;
                    control.type = type;
                    control.value = value;
                    control.addEventListener( eventName, eventBehaviour );
                    document.body.appendChild( control );
                },
                setupPage: function() {
                    Base.Controllers.addContainer( "div", "divInfo", "Here will be the result data." );
                    Base.Controllers.addControl( "input", "inputLatitude", "text",
                                "Latitude", "click",
                                function() { this.value = ''; }
                    );
                    Base.Controllers.addControl( "input", "inputLongitude", "text",
                                "Longitude", "click",
                                function() { this.value = ''; }
                    );
                    Base.Controllers.addControl( "input", "inputZoom", "text",
                                "Zoom", "click",
                                function() { this.value = ''; }
                    );
                    Base.Controllers.addControl( "input", "buttonAjaxTest", "button",
                                "click me", "click",
                                function() {
                                    var httpMethods = new Enums( "http" );
                                    var container = document.getElementById( "divInfo" );
                                    var request = new Ajax();
                                    request.onreadystatechange = function() {  
                                        if ( request.readyState == 4 ) {
                                            container.innerHTML = request.statusText;
                                            if ( request.status == 200 ) container.innerHTML = request.responseText;
                                        }
                                    };

                                    var latitude = document.getElementById( "inputLatitude" ).value;
                                    var longitude = document.getElementById( "inputLongitude" ).value;
                                    var zoom = document.getElementById( "inputZoom" ).value;
                                    var endpoint = "/mapimage/generate/bing/static/" + latitude + "/" + longitude + "/" + zoom;
                                    console.log( endpoint );

                                    request.open( httpMethods.Get, endpoint, true );
                                    request.send( null );
                                    container.innerHTML = "<img src='/img/loader.gif'> Awaiting for the server response...";
                                }
                    );
                }
            }
        };

        var instance = Base;
        return instance;
    }

    function Enums( inputType ) {
        function getEnumCollection( type ) {
            switch ( type ) {
                case "http":
                    return HttpMethods;
                default:
                    return null;
            }
        }

        var HttpMethods = {
            Post: "POST",
            Get: "GET"
        };

        var instance = getEnumCollection( inputType );
        return instance;
    }

    function Engine() {
        var ui = new UI();
        var Base = {
            setFunctionMain: function( objectFunction ) {
                window.onload = objectFunction;
            }
        };

        Base.setFunctionMain( ui.Controllers.setupPage );
    }

    var engine = new Engine();

</script>
\$\endgroup\$
  • \$\begingroup\$ gist.github.com/Zirak/3373067 \$\endgroup\$ – Florian Margaine Nov 28 '13 at 15:17
  • \$\begingroup\$ @Florian: care to provide some background? \$\endgroup\$ – Groo Nov 28 '13 at 15:26
  • 1
    \$\begingroup\$ Not a JS expert so I'll only comment: Why use the Base object? That's an object that relates to the HTML DOM. You don't seem to be using any of those features in your code snippet, so why not attach the various functions directly on to the prototype of each of your object functions? Also, why does every object function also automatically create one instance of itself? Shouldn't those be created separately, and/or only if needed? This is a great question BTW, can't wait to read the answers. \$\endgroup\$ – Shivan Dragon Nov 28 '13 at 15:27
  • \$\begingroup\$ @ShivanDragon Why use the Base object? answer: for structuring and some hiding options (encapsulation). ... relates to the HTML DOM. - where does it relate to DOM? It's just an object, where some functions work with DOM and that's all. so why not attach the various functions directly on to the prototype of each of your object functions?, answer: because you such a suggested protoype will be public and isn't encapsulated. Also The need in Base is for a clean well-structered code with the good use of it and it wouldn't look like a garbage. \$\endgroup\$ – user31341 Nov 28 '13 at 16:26
  • \$\begingroup\$ @ShivanDragon Also, why does every object function also automatically create one instance of itself? answer: for the getting a copy of instance when just creating it, less code and more elegant (as for my opinion). Shouldn't those be created separately, and/or only if needed? - As for me - now, because it wouldn't be look like a well structured class. PS: I'n not an expert in JS too, my first language , which I have to use professionaly is C#, so I came from C# and trying to implement the thins I've looked in C#. \$\endgroup\$ – user31341 Nov 28 '13 at 16:29
2
\$\begingroup\$

When talking about OOP, there are several concepts which are common to OOP languages, like encapsulation, dynamic dispatch, polymorphism, and abstraction. Of all these, I can only see that you are trying to implement encapsulation (in the sense of information hiding), although you could still do it slightly simpler in my honest opinion.

Generally, if your functions are not members of the parent function object, but merely contained inside variables, they are private to the outside world, so that alone is enough to achieve hiding. Using an additional object (Base, as you call it) achieves nothing in this direction and only adds noise (again in my honest opinion). No outside object will ever be able to access it anyway.

If you are trying to mimic OOP style programming in JavaScript, think how you would implement a polymorphism (i.e. create a derived class which has access to base class' methods) using your current convention.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the great answer. I must make a remark , because you wiil understand why did I make such code. I came from C# lang and JS I'm only learning. Trully... I don't event imagine how to create a normal polymorphism, which will be similar to C# with virtual/override keywords, as for the inheritance, I can imagine that it could be done just with the object copying in JS. \$\endgroup\$ – user31341 Nov 28 '13 at 16:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy