Understanding JavaScript Modular Template

I am trying to write the "best" javascript.

Below is one sample that I found, and I'm trying to accept it. However, I am a bit confused about its use.

Say, for example, I have a page called "Jobs". Any JS functionality on this page will be encapsulated as:

window.jobs = (function(jobs, $, undefined){ return { addNew: function(){ // job-adding code } } })(window.jobs|| {}, jQuery); $(function(){ $('.add_job').on('click', function(event){ event.preventDefault(); window.jobs.addNew(); }); }); 

As you can probably subtract, everything I did is replaced with all the code that would sit inside a function of an anonymous event handler, with a function call in my global task object. I'm not sure why this is good, except that it reduced the possibility of variable collisions and made it all a little tidy, but it is good enough for me.

Probably a rather obvious question: all my events-related events are still sitting outside my brilliant object of new assignments: where should it be? Inside the assignment object? Inside the return object inside the job object? Inside the init () function?

I'm just trying to get an idea of ​​a stable base structure for easy function input. I do not create JS applications, I would just like to write code that is a little more reliable and supported than it is currently. Any suggestions are welcome :)

+4
source share
4 answers

You can break the application in any number of modules / objects that you like.

For example, you may have another object / module that caches and defines all of your DOM nodes and another that handles any event. For example:

 (function ( win, doc, $, undef ) { win.myApp = win.myApp || { }; var eventHandler = { onJobClick: function( event ) { event.preventDefault(); myApp.addNew(); } }; var nodes = (function() { var rootNode = $( '.myRootNode' ), addJob = rootNode.find( '.add_job' ); return { rootNode: rootNode, addJob: addJob }; }()); $(function() { myApp.nodes.addJob.on( 'click', myApp.handler.onJobClick ); }); myApp.nodes = nodes; myApp.handler = eventHandler; }( this, this.document, jQuery )); 

It doesn't really matter how you create singleons in this (modular) template, or as a literal, constructor, Object.create() or something else. It must meet your requirements.

But you should try to create as many special modules / objects as needed. Of course, if it makes sense to split these singletones / modules / objects into several javascript files and load them on demand, and before you can say “knife”, you are in the world of modular programming templates dealing with requireJS and AMD or CommonJS modules.

+2
source

Encapsulation is all right: you could just declare addNew in jQuery closure, and you avoid the global scope anyway. I think that what you get is rather an implementation of something close to the MVC architecture.

Something that I like to do is to create an object that you create using the DOM element and which takes care of its own bindings / provides methods for accessing its controls, etc.

Example:

  // (pretend we're inside a closure already) var myObj = function(args){ this.el = args.el; // just a selector, eg #myId this.html = args.html; this.bindings = args.bindings || {}; } myObj.prototype.appendTo = function(elem){ elem.innerHTML += this.html; this.bindControls(); }; myObj.prototype.remove = function(){ $(this.el).remove(); // using jQuery }; myObj.prototype.bindControls = function(){ for(var i in this.bindings){ // event#selector : function var boundFunc = function(e){ return this.bindings[i].call(this,e); }; $(this.el).on(i,boundFunc); } }; 
+1
source

The way you do it right now, exactly the way I do it, I usually create window objects inside the anonymous function itself and then declare it inside it (in this case: jclass = window.jClass).

 (function (jClass, $, undefined) { /// <param name="$" type="jQuery" /> var VERSION = '1.31'; UPDATED_DATE = '7/20/2012'; // Private Namespace Variables var _self = jClass; // internal self-reference jClass = window.jClass; // (fix for intellisense) $ = jQuery; // save rights to jQuery (also fixes vsdoc Intellisense) // I init my namespace from inside itself $(function () { jClass.init('branchName'); }); jClass.init = function(branch) { this._branch = branch; this._globalFunctionality({ globalDatePicker: true }); this._jQueryValidateAdditions(); //put GLOBAL IMAGES to preload in the array this._preloadImages( [''] ); this._log('*******************************************************'); this._log('jClass Loaded Successfully :: v' + VERSION + ' :: Last Updated: ' + UPDATED_DATE); this._log('*******************************************************\n'); }; jClass._log = function() { //NOTE: Global Log (cross browser Console.log - for Testing purposes) //ENDNOTE try { console.log.apply(console, arguments); } catch (e) { try { opera.postError.apply(opera, arguments); } catch (e) { /* IE Currently shut OFF : alert(Array.prototype.join.call(arguments, ' '));*/ } } }; }(window.jClass= window.jClass|| {}, jQuery)); 

The reason I leave them completely anonymous like this is because even in a different file I want to add much more functionality to this jClass. I just create another:

 (function jClass, $, undefined) { jClass.newFunction = function (params) { // new stuff here }; }(window.jClass = window.jClass || {}, jQuery)) 

As you can see, I prefer the object.object notation, but you can use the object literal object: object, it up to you!

In any case, leaving it all separate and encapsulating without the actual page logic, this will simplify this in the globalJS file, and every page on your site will be able to use it. For example, an example below.

 jClass._log('log this text for me'); 

You do not want to intertwine the model logic with your business logic, so yours on the right path separating the two and allowing your global namespace / class / etc to be more flexible!

+1
source

Here you can find a comprehensive study of the module structure: http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html It covers all aspects of the modular approach with the block module. However, in practice, you will have a number of files encapsulating your code, so the question is how to combine their property. AMD ... several HTTP requests generated each time the module is loaded is more likely to hurt your response to the page. This way you can use CommonJS for a single JavaScript file, suitable for use in a browser. Take a look at how easy this is http://dsheiko.imtqy.com/cjsc/

0
source

All Articles