« Image hotlinking — the problem continues, one solution remains

Five posts I wrote that will help you find a programming job, recession or no recession »

Practical JavaScript — three code snippets to get you thinking

December 10th, 2008 by Brian | 5 Comments »

There are some fairly complicated JavaScript paradigms these days. Class inheritance, templating, client-side data storage, and the DOM in HTML5 are just a few. These are great to learn about and experiment with, but many of us return to the grind without a lot of practical knowledge we can use consistently. Here are a few code snippets to get you thinking and coding more efficiently.

Repeatability with chaining

Chaining allows you to call a method, or several methods on an object without having to constantly reference that object. If you are dealing with an object literal that has namespaces, then this can really shorten up your code and keep things clean. The following example demonstrates the basic concept behind chaining.

function doSomething() {
	this.justDoIt = function( a ) {
		alert( a );
		return this;
	}
	this.justDoItAgain = function( b ) {
		alert( b );
		return this;
	}
	this.justGetIt = function( c ) {
		return c;
	}
};

new doSomething().justDoIt( 1 )
	.justDoIt( 2 )
	.justDoItAgain( 3 )
	.justGetIt( 4 );

You can see how the methods justDoIt() and justDoItAgain() perform an action (in this case an alert), and then return a reference to the parent constructor. When you create a new object, and call one of those methods, you get the benefit of being able to call them again. However, if you look at the justGetIt() method, the argument passed through is what gets returned. At any point you call this method the chain is broken.

Reuse with established norms

On occasion I need to create some functionality that I am sure has already been developed elsewhere and tested, too. Not full fledged plugins, or widgets, but an algorithm that efficiently manages a single task. Many of these algorithms exist in various forms in other languages like Java and C#, and can easily be ported over to JavaScript.

The code below is a form of the Fisher-Yates algorithm, which shuffles any array-like structure. I added an additional element, which is to pick the first N elements, as specified through an argument. If you run a contest, and want to randomly select a number of winners, then this is a good way to accomplish that.

function pull( a, n ) {
	var i = a.length;
	if ( i == 0 ) {
		return false;
	}
	while ( --i ) {
		var j = Math.floor( Math.random() * ( i + 1 ) );
		var iArr = a[ i ];
		var jArr = a[ j ];
		a[ i ] = jArr;
		a[ j ] = iArr;
	}
	return a.slice( 0, n );
}

alert( pull( [ 1, 2, 3, 4, 5, 6, 7 ], 3 ).toString() );

A good place to uncover these, other than through Google, is to use Stack Overflow. I got some great responses to a question I asked regarding the best algorithm for determining the high and low in an array of numbers. These snippets are reusable and established, and typically perform better. They also teach you to think about problems mathematically, which is not my strongest skill.

Edit (12/11/08):

It was brought to my attention that the above algorithm is not entirely efficient. Why iterate through the entire set, when you only need three? I cannot argue with that, and it does make sense. Without further testing, my first instinct would be to replace while( ––i ) with while( ––n ), remove the slice, and return the array. If anyone has a better suggestion, please feel free to mention it.

Flexibility with preferences

A handoff to a client that has an in-house IT staff can be a tricky task. You want to provide plenty of flexibility, but you also want to place a tight control on some aspects of the Web application. This is usually done through a micro-API with settings or preferences.

The following code is an example of constructor type checking, or object validation, on an object literal as a group of settings. I prefer this approach when I use a micro-API because it is easier to communicate what needs to be passed through to the application. It is friendlier to ask for a First Name or Birth Date, then it is to ask for the fourth parameter, which needs to be a date.

function validateObjTypes( rules, constructs ) {
	var errors = [];
	var isObjType = function( obj, objType ) {
		return ( obj.constructor.name == objType );
	}
	for ( var i in rules ) {
		if ( !isObjType( constructs[ i ], rules[ i ][0] ) ) {
			errors[ errors.length ] = { i : [ "The '", rules[ i ][1], "' must be a ", rules[ i ][0] ].join( "" ) };
		}
	}
	return errors;
}

function doSomething( settings ) {
	var errors = validateObjTypes({
		firstName : [ "String", "First Name" ],
		jobTitle : [ "String", "Job Title" ],
		workPhone : [ "Number", "Work Phone" ],
		birthDate : [ "Date", "Birth Date" ]
	}, settings );
	if ( errors.length == 0 ) {
		/* ... perform actions on settings here ... */
	} else {
		/* ... loop errors and display ... */
	}
}

var birthDate = new Date();
birthDate.setFullYear( 1976, 11, 03 );

doSomething({
	firstName : "Brian",
	jobTitle : "Software Engineer",
	workPhone : 5555551212,
	birthDate : birthDate
});

This abstracts the functionality for the validation portion, and for doSomething(). Whoever needs to “do something” will never know what is happening behind the scenes. Also, if you find that you need to validate based upon strict data type formats, you can call a different validation function that compares each setting to regular expressions. It would be the same doSomething(), but with new business rules that dictate what can come through the API.

Edit: (12/11/08)

Someone on Reddit pointed out that to my chagrin, IE does not allow you to retrieve a constructor’s name. A link was posted to Stack Overflow detailing the problem. Conceptually the example still works, but there is an edit that you would need to make that I believe would force this to behave correctly in IE as well. You can compare two constructors as objects. I have not tested this thoroughly, and do not know at what point it would fail with regard to an object’s prototype, but it appears to work at first glance.

function validateObjTypes( rules, constructs ) {
	var errors = [];
	var isObjType = function( obj, objType ) {
		return ( obj.constructor == objType.constructor );
	}
	for ( var i in rules ) {
		if ( !isObjType( constructs[ i ], rules[ i ][0] ) ) {
			errors[ errors.length ] = { i : [ "The '", rules[ i ][1], "' must be a ", rules[ i ][0] ].join( "" ) };
		}
	}
	return errors;
}

function doSomething( settings ) {
	var errors = validateObjTypes({
		firstName : [ new String(), "First Name" ],
		jobTitle : [ new String(), "Job Title" ],
		workPhone : [ new Number(), "Work Phone" ],
		birthDate : [ new Date(), "Birth Date" ]
	}, settings );
	if ( errors.length == 0 ) {
		/* ... perform actions on settings here ... */
	} else {
		/* ... loop errors and display ... */
	}
}

var birthDate = new Date();
birthDate.setFullYear( 1976, 11, 03 );

doSomething({
	firstName : "Brian",
	jobTitle : "Software Engineer",
	workPhone : 5555551212,
	birthDate : birthDate
});

If anyone could provide any further feedback, it is always welcome.

Tags: , , ,

Posted in: Cascading Style Sheets, JavaScript

This entry was posted on Wednesday, December 10th, 2008 at 7:07 pm and is filed under Cascading Style Sheets, JavaScript.

You can follow any responses to this entry through the RSS 2.0 feed.

Both comments and pings are currently closed.

5 Responses to “Practical JavaScript — three code snippets to get you thinking”

  1. [...] Practical Javascript – Three Code Snippets to Get You Thinking (Brian Reindel) [...]

  2. Peter Cooper says:

    Interesting post. I love the formatting – it’s so easy to read and the code examples are integrated splendidly. I’d like to see more posts along these lines (I’m still just a JavaScript “dabbler”).

  3. Brian says:

    Hi Peter,

    Thanks for the great feedback. I hope to be posting more like this in the immediate future. Best of luck in your JavaScript dabbling!

  4. Elad Ossadon says:

    Nice post.

    You could check constructors without instantiating a new instance for each.

    “a”.constructor==String
    (0).constructor==Number

    Getting their names (which still doesn’t work on IE) can be done like:

    constructor.name || constructor.toString().match(/function (.*)\(/)[1]

    Which will of course give nothing for anonymous functions but will work for all native JS types and named functions. Can be simply fixed by assigning all anonymous function classes a name property:

    var F=function () {};
    F.name=”F”;

  5. [...] Practical JavaScript — three code snippets to get you thinking [...]