Plugin parade #3: methods

Take a look at this code snippets:

String.prototype.trim = function(){ 
	return this.replace(/(^\\s+|\\s+$)/g, "");
};

It provides a very powerful method, it can often be useful when working with Strings, eg. when formatting text from form inputs. Adding it as String method via the String.prototype makes the usage easier then a class global function. Instead of trim(“somestring”), you can simply call “somestring”.trim().

So what’s the problem? Why not just add all kind of stuff to different prototypes? We could add all the new Array methods supported by Firefox, which are missing in other browsers, like forEach. Add while we are at it, we could add some useful methods to the Object prototype, and use these methods with all our objects. Like this debug method:

// don't try this at home!
Object.prototype.debug = function(){ 
	console.debug("debugging " + this);
	for(key in this) {
		console.debug("key: " + key);
		console.debug(this[key]);
	}
};

Adding the above to your scripts would shatter jQuery and every other script, library or framework that relies on for(key in object) loops. Something that you’d rather avoid to do.

Consider the debug method above, and this example:

var myObject = {
  name: "peter",
  age: 21
};
myObject.debug();

What do you expect what be logged on your Firebug console? This?

debugging [object Object]
key: name
peter
key: age
21

Close, and wrong. You get this:

debugging [object Object]
key: name
peter
key: age
21
key: debug
function()

Ok, nothing to worry about, eh? We added the debug method to the Object prototype, so it makes sense that it appears there.

But it also appears everywhere else, something we definitely don’t want.

So no Object.prototype, what about problems with String or Array prototypes? The same problem applies: When you use a for(key in object) loop on Strings or Arrays, you’d also find the added methods. As there is basically no need to use that loop on Strings or Arrays, it’s more up to your enviroment. To you work with others or with code from others, that you don’t control? Is there any chance that there is a loop on an extended object? Bad. Go to prison. Do you work alone and/or you have control over all code involved? Fine. Read on.

Whew, that was a rather long introduction. Now only sugar for the rest of the day: The “methods” plugin!

Currently it provides six sexy String methods (trim, camelize, startsWith, endsWith, truncate and stripTags) and seven sexy Array methods (forEach, every, some, map, filter, indexOf and unique). Apart from unique, the Array methods are already provided by Firefox as “Javascript 1.7”. For that reason, both plugins add only methods that don’t already exists. To guarantee compability, an extensive testsuite tests for both native and new methods.

Array methods plugin source (contains documentation)
String methods plugin source (contains documentation)
Testsuite
Mozzila’s documentation for the new Array methods

In case you don’t want to use the complete package or can’t use the prototype approach: Feel free to pick only those methods that you need or only the involved regular expressions (from trim, camlize and stripTags).

If you have useful methods that you’d like to provide: Just let me know. Some additional Date methods are very appreciated.

Prison

So you are in prison, need some array/object iterators and can’t or don’t want to use prototype extensions? Try these, posted by Michael Geary on the jQuery discussion list:

function objectEach( obj, fn ) {
    for( var name in obj )
        if( fn( obj[name], name ) === false )
            break;
}

function arrayEach( ary, fn ) {
    for( var i = 0, n = ary.length;  i < n;  i++ )
        if( fn( ary[i], i ) === false )
            break;
}

He also posted examples how they work:

objectEach(
    { a:'ay', b:'bee', c:'see' },
    function( value, name ) {
        return confirm( name + ': ' + value );
    }
);

arrayEach(
    [ 'ay', 'bee', 'see' ],
    function( value, index ) {
        return confirm( index + ': ' + value );
    }
);

In each one you can cancel the iteration by clicking cancel on the confirm dialog.

For simple iterations that you'd like to stop at some point these are much better then jQuery's $.each (which is mostly for internal usage).

-Jörn

No more comments.
  1. brent

    hi, interesting post. just FYI, you are missing a couple of “\”s in your String.prototype.trim() regexp. they’re in the plugin though….
    so maybe your editor just dropped them.

  2. Thanks for the comment. They were indeed dropped by the editor, I escaped them now properly.

  3. Hello, my name is Alex, i’m a newbie here. I really do like your resource and really interested in things you discuss here, also would like to enter your community, hope it is possible:-) Cya around, best regards, Alex!

  4. Hi Alex,

    you could start by joining jQuery’s discussion list: http://jquery.com/discuss/