Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JQuery JavaScript Design: Self Executing Function or Object Literal? [closed]

I'm curious as to if there are any best practices relating to JQuery when constructing encapsulated code blocks.

Generally, when I construct a page I like to encapsulate the functions used within that page inside an object. This allows me some encapsulation when building applications. There's nothing I hate more than seeing a JavaScript file with a bunch of this

function doSomethingOnlyRelevantOnThisPage() {
    // do some stuff
}

I this makes for messy design, and doesn't really encapsulate functionality nicely.

Commonly in many frameworks, there is a standard that is used to perform this encapsulation.

In Mootools they favor the Object Literal Notation:

var Site = {        
    // properties and methods
}

In YUI they favor the Self Executing Function notation:

(function() { // properties and methods })()

The nice thing about the second example is that a closure is created, thus allowing you to define private properties and methods.

My question is this: Do any JQuery aficionados have any best practices for creating these cleanly encapsulated structures? What is the rationale behind their use?

like image 563
steve_c Avatar asked Oct 09 '08 18:10

steve_c


2 Answers

Since I've been working with jQuery for a while now, I've decided on a standard pattern that works well for me.

It's a combination of the YUI module pattern with a bit of jQuery plugin pattern mixed in.. We ended up using the self executing closure pattern. This is beneficial in a few ways:

  1. It keeps code to a minimum
  2. It enforces separation of behavior from presentation
  3. It provides a closure which prevents naming conflicts

This is what it looks like:

;(function($) {        
    var myPrivateFunction = function() {
    };

    var init = function() {
        myPrivateFunction();
    };

    $(init);
})(jQuery);

We realized that assigning the result of the function execution, similar to the YUI module pattern, exposes code that could potentially be called from within presentation code. We want to prevent this, so this pattern fits.

Of course we could have written the init method inline, without defining a variable for the function. We agreed that explicitly defining the init function made the code clearer to readers.

What happens if we want to share functions between pages/external js files? We simply hook into the existing mechanism that jQuery provides for extending the jQuery object itself - the extend function.

If the functions are static, we use $.extend, and if they operate over a wrapped set, we use the $.fn.extend function.

Hope this helps someone.

like image 103
steve_c Avatar answered Oct 15 '22 19:10

steve_c


I use YUI and jQuery when developing (YUI widgets and a few convenience functions, jQuery selectors and javascript "extensions"), and the general javascript template I use is this:

/*global YAHOO, $ */

// Create the public-scope accessable namespace for this page
YAHOO.namespace('Project');

YAHOO.Project.page = function() {
    // Private members

    var self = {};

    // Public members
    var pub = {};

    pub.init = function() {

    };

    return pub;
} ();

// When the DOM is loaded, initialize this module
$(document).ready(YAHOO.Project.page.init);

Now clearly, you can remove the YAHOO.namespace() call if you don't want to use YUI, but that's the basic outline. It uses object literal notation, but also allows you to define private properties and methods.

Just remember that when calling private members or referencing private variables to reference them as self.funcName(). You can define them outside of the self object, but then you get a mismash everywhere in your object, where you're trying to figure out if size_of() is a private method or defined globally somewhere else.

like image 35
Dan Hulton Avatar answered Oct 15 '22 21:10

Dan Hulton