diggingforfire
diggingforfire

Reputation: 3399

Keeping your javascript structured and tidy (as an OO programmer)

I've recently been playing with javascript, HTML5, chrome extensions, jQuery, and all that good stuff. I'm pretty impressed so far with the possibilities of javascript, the only thing I struggle with is structuring my code and keeping it tidy. Before I know it, functions are scattered all over the place. I've always done my programming in an object oriented manner (C++ and C#), and I find myself not being able to keep things tidy. It feels like I always end up with a bunch of static util functions, were I to 'think' in C#.

I've been looking for some information on objects in javascript, but it seems to come down to wrapping functions in functions. Is this a good way of structuring your codebase? On the surface it seems a bit hackish. Or are there other ways of keeping things tidy for an OO mindset?

Upvotes: 7

Views: 898

Answers (5)

Lambda Fairy
Lambda Fairy

Reputation: 14676

I generally follow the make-an-anonymous-function-then-call-it pattern. Basically, you create an inner scope and return a single object containing your interface. Nothing else escapes, because it's all trapped within the function scope. Here's an example using jQuery:

var FancyWidget = (function($) {
    // jQuery is passed as an argument, not referred to directly
    // So it can work with other frameworks that also use $

    // Utility functions, constants etc can be written here
    // they won't escape the enclosing scope unless you say so
    function message(thing) {
       alert("Fancy widget says: " + thing);
    }

    // Make a simple class encapsulating your widget
    function FancyWidget(container) {
        container = $(container); // Wrap the container in a jQuery object
        this.container = container; // Store it as an attribute

        var thisObj = this;
        container.find("#clickme").click(function() {
            // Inside the event handler, "this" refers to the element
            // being clicked, not your FancyWidget -- so we need to
            // refer to thisObj instead
            thisObj.handleClick();
        });
    }

    // Add methods to your widget
    FancyWidget.prototype.handleClick = function() {
        this.container.find("#textbox").text("You clicked me!");
        message("Hello!");
    };

    return FancyWidget; // Return your widget class
                        // Note that this is the only thing that escapes;
                        // Everything else is inaccessible
})(jQuery);

Now, after all this code executes, you end up with one class, FancyWidget, which you can then instantiate.

You can define multiple classes this way too; instead of using return FancyWidget, you can return an object literal instead:

    return {
        FancyWidget: FancyWidget,
        Frobnicator: Frobnicator,

        // Nested namespaces!
        extra: {
            thing: thing,
            blah: blah
        }
    };

Upvotes: 2

Jeffrey Sweeney
Jeffrey Sweeney

Reputation: 6114

One important aspect to remember about Javascript is that it is a prototypical language. Functions can be objects, and anything can be put on the object, often affecting related objects in the process. There's no official way to 'extend' an object because of this. It's a concept that I still have a hard time understanding.

Javascript 'acts' like any other OOP language for the most part, with some exceptions, namely extending objects (http://jsweeneydev.net84.net/blog/Javascript_Prototype.html).

After extensive research, I did find a very, very light-weight way to simulate expanding objects (I'm using using it in my GameAPI). The first field is the parent object, the second is the object that expands.

extend  : function(SuperFunction, SubFunction) {

    //'Extends' an object

    SubFunction.prototype = new SuperFunction();
    SubFunction.prototype.constructor = SubFunction;
},

This link might clear up some problems and misconceptions: http://www.coolpage.com/developer/javascript/Correct%20OOP%20for%20Javascript.html

Personally, I tend to be anti-framework, and I haven't seen a framework yet that doesn't force the programmer to significantly change their programming style in this regard anyway. More power to you if you find one, but chances are you won't really need one.

My best advise is to try to adapt to Javascript's prototypical style, rather than force old methodologies on it. I know it's tricky; I'm still trying to myself.

Best of luck diggingforfire.

Upvotes: 2

Tadeck
Tadeck

Reputation: 137320

Using some framework designed to meet similar requirements may be a good idea.

But there are some things you should really follow to be efficient:

  • remember about closures in JavaScript and do not forget about var keyword,
  • use callbacks where possible and reasonable, JavaScript is asynchronous by nature,

Upvotes: 1

Charles Ma
Charles Ma

Reputation: 49141

One of the best OOP javascript libraries out there is Google's Closure library http://closure-library.googlecode.com/svn/docs/index.html

It's structured in a way that OOP programmers will be familiar with especially if you come from a java/C# background. Have a look at the source code of any file and it should feel right at home as an OOP programmer. http://closure-library.googlecode.com/svn/docs/closure_goog_graphics_canvasgraphics.js.source.html

Upvotes: 1

Wes Crow
Wes Crow

Reputation: 2967

I have never used this personally, but have seen backbone.js referenced many times to this question. See at: http://documentcloud.github.com/backbone/

Upvotes: 1

Related Questions