JasonWyatt

This blog is full of stuff, and things.

Find my resume.

permalink

Anonymous Classes with JavaScript and Self-Calling Functions

I was messing around with Firebug today, trying to test out a concept for event handling and I didn’t want to have to go through all the pomp and circumstance of creating a legitimate class in the firebug console so I dreamed up a way to make an anonymous class. Here’s what I came up with: (I left out the event handling stuff)

var a = new (function(name){
    this.sayHello = function(){
        console.log("Hello, ", name, "!");
    };
})("Jason");

a.sayHello();

What’s going on here? Remember that classes in JavaScript are just functions that can be called with the new keyword to instantiate a new object of the class defined by that function. (the function acts as the class’s constructor) So, we’re setting a variable, a, to a new instance of a class whose constructor is an anonymous function wrapped in parentheses to encapsulate it.

We can take this concept even further by working with our anonymous class’s prototype after we instantiate it. However, I cant really think of a practical reason to do this other than to make the code prettier, if you know - leave a comment.

var a = new (function(name){
    this.name = name;

    this.sayHello = function(){
        console.log("Hello, ", this.name, "!");
    };
})("Jason");

a.constructor.prototype.sayGoodbye = function(){
    console.log("Goodbye, ", this.name,".");
};

a.sayHello();
a.sayGoodbye();

Why do I care?

Anonymous classes can be useful for things like mock objects in the case of unit tests. Imagine that you have a unit test which checks that a static method called serialize() correctly serializes an instance of its class, MyClass to a JSON string. We don’t really want to create a new instance of the real class if we only need to check that certain attributes are correctly serialized. Check it out:

/* 
 Lots of code to describe MyClass
 */
MyClass.serialize = function(instance){
    return JSON.stringify({
        name: instance.getName(),
        longList: instance.getList()
    });
};

/*
 In another file, for our unit test...
 */
function testSerialize(){
    var data = {
        name: "Awesome object.",
        longList: [1,2,3,4]
    };

    var actualResult = MyClass.serialize(new (function(settings){
        this.getName = function(){
            return settings.name;
        }
        this.getList = function(){
            return settings.longList;
        }
    })(data));

    assertEqual(JSON.stringify(data), actualResult);
}

I realize that this probably isn’t all that novel, but it’s an example of how JavaScript is a great language for allowing programmers to be creative.

permalink

Dynamically Instantiate a Dojo Class At Runtime

Need to create an instance of a class in Dojo without knowing what that class is ahead of time? Will you only have the name of the class that you want to instantiate? Check this out:

/**
 * Create a new instance of a Dojo class.
 *
 * @param className
 *    (String) A fully-qualified name for class, such as 
 *    "my.pack.age.Class"
 * @param constructorSettings
 *    (object) An object that will be passed on to the 
 *    class's constructor.
 */
function instantiateDojoClass(className, constructorSettings){
    try {
        dojo.require(className);
        
        /*
         * Eval the class name to get a reference to the 
         * function, then call it as a constructor using the 
         * constructorSettings object as an argument.
         */
        var obj = new (eval(className))(constructorSettings);
    } catch (e){
        /*
         * Handle any errors that might happen.
         */
        if(console){
            console.error("Could not instantiate %s: %s", classsName, e.message);
        } else {
            alert("Could not instantiate "+className+": "+e.message);
        }
        throw e;
    }
}

The real trickery here is in the line:

var obj = new (eval(className))(constructorSettings);

This evaluates the string className to retrieve a reference to the dojo function that was ‘created’ by the call to dojo.require(..), then calls that function as a constructor by using the new keyword. It passes the constructorSettings object on to the constructor, just like you’d do with any normal dojo instantiation.

permalink

JS One-Liner: Determine If A Word Is In An Array.

(new RegExp("(,|^)"+myString+"(,|$)")).test(myArry.join(","))

permalink

Creating a Ruby-style each() for JavaScript

Yep, this is another post that modifies built-in prototypes for JavaScript to add functionality I wish was already there.

I’ve been learning Ruby lately and I’ve really fallen in love with the idea of “blocks” and the way they’re used in that language. I thought it could be useful to introduce some of the functions that use blocks from Ruby into JavaScript using function objects.

This code adds a .each() function to every object in the runtime:

Object.prototype.each = function(fn){
    var scope = arguments.length > 1 ? arguments[1] : window;
    for(var i in this){
        if(this[i] instanceof Function)
            continue;
        if(fn.call(scope, this[i], i) == false)
            break;
    }
    return this;
};

Let’s walk through what’s going on here:

  1. Give all objects a new function called “each” by giving Object.prototype a new function called “each”. Let each accepts at least one argument: fn, a function object.
  2. If more than one argument was specified, define the second argument to be the scope within which we’ll call the function. Otherwise, set the scope to the window object.
  3. Iterate through every member of this, the object on which each() was invoked:
    1. Skip the member if it’s a function object itself (we only want to iterate over non-functions).
    2. Call the function within the defined scope and with two parameters: the member itself, and it’s identifier.
    3. If the function returns false, interpret this as a signal to stop iterating.
  4. Return the object on which each() was invoked, to support function chaining.

What are some other features you’ve created “translations” for a language based on another language?

permalink

Built-in Logging Capability for Strings in JavaScript

I really like playing around in JavaScript a lot, and sometimes this involves hacking with the built-in prototypes.

Today I found myself wanting an easy to use way to log messages, errors, warnings and fire off alerts directly from a string object. (mostly just to make things look prettier, I’ll admit) I decided to tweak String’s prototype directly and add five new functions: log(), warn(), debug(), error(), and alert():

String.prototype.log = function(){
    console.log(this+"");
};
String.prototype.error = function(){
    console.error(this+"");
};
String.prototype.debug = function(){
    console.debug(this+"");
};
String.prototype.warn = function(){
    console.warn(this+"");
};
String.prototype.alert = function(){
    alert(this+"");
};

Now you can print text out to the console simply by calling log() on any string:

"This is the text I want to log".log();

Keep in mind you can always tweak the internals of these functions so that they’ll do whatever you want. (e.g. have them append to the innerHTML of a particular DOM node)