Voorstel nieuwe JavaScript benadering

Zoals Sjoerd onlangs al aangaf tijdens de nieuwsjaarsmeeting, is het JavaScript kennisniveau van het front-end team aanzienlijk vooruit gegaan. Naast een steeds groter wordende codebase zijn er ook interne standaarden beschikbaar als het gaat om naamgeving en best practices. Waar we mijns inziens echter nog wel aan kunnen werken is de manier waarop we JavaScript toepassen.

Momenteel is het namelijk zo dat we een redelijk procedurele JavaScript aanpak hanteren waarbij we louter scheiding toepassen in projectgerelateerde functies (functions.js), event delegatie (events.js) en eventuele losse "classes" of jQuery extensions / plugins (frmhandler.class.js / jquery.plugin.js).

Nieuwe aanpak

Ik loop al enige tijd met het idee om deze aanpak naar een nieuw, hoger en professioneler niveau te tillen. Hierbij is het uiteraard essentieel dat de nieuwe aanpak ook voldoende voordelen oplevert met betrekking tot onderhoudbaarheid, leesbaarheid en performance. Na wat onderzoek en tryouts ben ik tot volgende constructie gekomen:
één globaal object, welke tevens dient als namespace, waarin alle JavaScript functionaliteit gebundeld wordt. Het voordeel hiervan is dat de global scope niet vervuild wordt, alle JavaScript functionaliteit zich netjes in 1 namespace bevindt en er dus geen kans is op collisions.

Centralisatie

Als design pattern heb ik gekozen voor een veredelde Singleton waarbij geen sprake is van instantiatie (middels de new prefix), alle methods zijn "static". Een voorbeeld van een dergelijke aanpak ziet er als volgt uit:

behavior.js		
/**
 * NEJA - New E-sites Javascript Approach
 * 
 * @author Boye Oomens 
 * @since 24-01-2010
 * 
 * @namespace NEJA
 */
var NEJA = {
	global: {
		foo: 'bar'
	},
	init: function () {
		NEJA.setup();
		NEJA.events();
	},
	setup: function () {
		/* Extend jQuery with utils */
		jQuery.extend(SBP.utils);
			
		/* Extend jQuery with plugins */
		jQuery.fn.extend(SBP.plugins);
		
		/* Initialise designer module if necessary */
		if ($.isset('#partyCreator')) {
			$.getScript('/library/min/?g=designr', function () {
				designr.init();	
			}, true);
		}
			
	},
	events: function () {	
		/* Handle external URLs */
		$('[rel*=external]').bind('click', NEJA.fn.setExtLinks);	
	},
	fn: {
		setExtLinks: function () {
			this.target = '_blank';			
		}
	},
	plugins: {},
	utils: {
		isset: function (selector) {			
			if (selector.constructor === String) {
				return (($(selector).length));	
			}			
			return false;
		}
	}
}

init.js
$(document).ready(NEJA.init);
	

Vaste "modules" aka properties

In het NEJA object, bevinden zich aantal vaste properties, qua naamgeving spreken deze properties aardig voor zich denk ik zo, maar aangezien er normaliter netjes comments bij elke property horen en dit nu niet het geval is zal ik even een korte toelichting geven:

Wat betreft de naam van de object literal heb ik nu een fictieve naam gepakt, dit zou in de praktijk de afkorting van de site moeten zijn.

De init method wordt aangeroepen als zijnde argument van de jQuery ready method in init.js en uitgevoerd wanneer de DOM-tree opgebouwd is.
Dit lijkt op het eerste gezicht op een overkill, ware het niet dat alle JavaScript files concatenated worden door Minify er dus geen sprake is van een "dure" HTTP request. Init.js zou in principe ook weggelaten kunnen worden waarbij het initialiseren verplaatst kan worden naar behavior.js, dit is iets waar ik nog niet over uit ben.

Meningen

Zelf heb ik deze aanpak al bij een aantal projecten toegepast en het werkt erg prettig moet ik zeggen. Uiteraard ben ik ook benieuwd hoe jullie (front-end) developers denken over deze constructie, en wat eventuele valkuilen kunnen zijn die ik over het hoofd gezien heb.