A Naive, JScript Compatible Getter Pattern

Modern JavaScript implementations let you define getters and setters for properties of objects. The new syntax involved will, of course, make your code incompatible with less capable JavaScript VMs if you chose to use it, but the behavior of the rest of your code will also be different, even when syntactically identical. This little experiment of mine was aimed to address the latter issue (well, at least for getters.)

The following is a naive implementation of getters that would be somewhat compatible with language supported getters in common usage (setters are just not possible!) Perhaps this technique could prove useful in some contexts but the reliance on type coercion makes it dubious…

Take, for example, the behavior of a rectangle:

var rect = new Rectangle(4,5);

rect.area; // returns 20

rect.width = 6;

rect.area; // returns 30

The area property updates dynamically, by way of a getter. With proper getters, you could implement the Rectangle class like so:

function Rectangle(width, height){
  this.width = width;
  this.height = height;

  this.__defineGetter__('area', function (){
    return this.width * this.height;
  });
}

Now let’s see the naive, JScript compatible approach:

function Rectangle(width, height){
  this.width = width;
  this.height = height;

  var that = this;

  var area = function(){};
  area.valueOf = function(){
    return that.width * that.height;
  };

  this.area = area;
}

The key idea here is that area is a complex value that will be coerced into a primitive by most operations, calling its valueOf method. Let’s see how well it works:

var rect = new Rectangle(4,5);

assert(typeof rect.area === 'function'); // it's really a function
assert(typeof +rect.area === 'number');  // but can be coerced into a number

assert(rect.area == 20);                 // type coercion
assert(rect.area !== 20);                // === and !== don't coerce type
assert(rect.area + 5 == 25);             // operator type coercion
assert(rect.area + 5 === 25);            // coercion happens before equality comparison

rect.width = 6;
assert(rect.area == 30);                 // area updates as expected

This is definitely a stretch of the intentions of the language, and as I mentioned, very dubious. But, if you could get away with it you would be able to utilize getter behavior on lesser JavaScript VMs without changing your API. Neat.

Edit: use valueOf, not toString. DUH

A Matter of Philosophy (and necessity)

The article comparing Mootools and jQuery is great — go ahead and take a gander. The author definitely did his research. In fact, there are only a few nitpicks I had with it.

The author demonstrates well his awareness of the different philosophies of each project. The aim of jQuery is to provide a succinct API for dealing with browser shortcomings and inconsistencies, whereas Mootools aims to be a framework for building web applications. This means Mootools includes things such as OOP patterns, and jQuery does not (and I don’t think that will change anytime soon.)

I happen to be a fan of small, modular pieces of functionality that can easily be plugged in when necessary, which is why the jQuery philosophy resonates more with me.*

Intermediate to Advanced Programmers

When the author mentions that intermediate to advanced JavaScript programmers would prefer Mootools, I believe he is speaking in the general sense, for there may also be cases where intermediate to advanced JavaScript programmers have their own methodologies to handle program structure — whether with OOP or something else. In such cases, jQuery might be more appealing precisely because it lacks the extras Mootools provides.

The author understands this point, no doubt, but I missed a more direct articulation of it, as someone in the situation described above.

I can also see how jQuery would appeal to designers and beginners who haven’t delt with, or had a need to deal with the complexities involved in larger application development. jQuery, with its succinct API, draws them in.

JavaScript Style

The author reiterates from time to time that Mootools has a more JavaScript-like style than jQuery. Well, that depends. JavaScript is a multi-paradigm language and depending on which paradigm you lean toward, that statement may prove true for you or it may not. If your style tends to be functional, you might find jQuery fits more snuggly alongside your braces and semicolons. I’ve gone through many stages as a JavaScript programmer, employing different styles, and I can’t say that one style or the other is more JavaScript like. Both prototypal or functional styles feel comfortable to me, though functional style JavaScript is probably less understood or used in general.

The Great Debate - Monkey patching

And then there is the great debate over extending global objects. This can be a deal breaker for some.

Mootools extends global objects to achieve its power and elegance. jQuery uses monadic like wrappers to achieve its power and elegance.

My personal view is that frameworks and third party modules should do as little modification to the global namespace as possible, so as not to conflict with the main application or other modules. If the application developer wants to modify the global namespace, that is their business, but third party code should play nice with others.

Extending global namespaces certainly feels good, but is it more powerful? Not necessarily; you could just as easily pass an object to a function rather than attach the function as a method to the object. But it certainly doesn’t look nearly as nifty.

If only there were a way to encapsulate changes to global objects to only within a certain scope…

That said, Mootools is intentionally exposing these language extensions as part of the framework it provides. If you choose Mootools then you don’t mind those extensions, or would have done similar extensions your self. As long as you are mindful of the potential for conflict, trouble should be avoidable.

Okay, I think I’ve gone on long enough. Great article, Aaron.

*And yet, I like Rails. People are weird…

RE: Null and Undefined as Objects in JavaScript

I regret not making everything an object, FWIW. “Make it look like Java” + lazy/fast machine types for numbers + zero time to implement in May 1995.
- Brendan Eich (creator of JavaScript)

Wouldn’t that have been something.

Don’t Push Your OOP On Me

Implementations of classical inheritance in JavaScript always leave a bad taste on my tongue. John Resig articulates why:

I’m not convinced by this argument. “Because it’s what we’re familiar with” does not imply that it’s the best solution - or even a good solution - neither does “everyone else is doing it.” I’ve been doing JavaScript development for a while now and I’m becoming less-and-less convinced that the traditional MVC/Classical inheritance styles of development (carried over from Java or Ruby, for example) do not translate to JavaScript/DOM well and can, in fact, be improved upon in some dramatic ways.

That said, I was working on a way to achieve multiple inheritance in JavaScript via mixins - but in a traditional prototypal manner! It’s cool man, really!

An Object That’s Not

In JavaScript, objects just love their prototypes. And why wouldn’t they? Whenever they are in need of a property, hey, they can always check up the inheritance chain and try to find it. It’s good to know someone always has your back!

But, what if no one had your back?

$ js
js> var obj = {};
js> obj.toString();
[object Object]
js> obj.__proto__ = null;
null
js> obj.toString();
typein:4: TypeError: obj.toString is not a function
js>

hwaaa!

js> obj+obj
typein:5: TypeError: can't convert obj to primitive type
js> typeof obj.__proto__
undefined
js>

Poor obj has no prototype to inherit from anymore - we set it to null. It knows nothing of the built in wonders inherited from Object.prototype. No toString, no hasOwnProprty, no nothing.

There’s even a way to wipe out Object.prototype for everyone (I’ll leave this as an exercise for the reader.)

Direct access to the inherited prototype can sure do some wacky things, indeed. I’ll post on the more useful functionalities I’ve found in a bit.

The Miller Device on null and Other Lowly Un-values

null and undefined are weird. Normally, you would check for them directly by using x === null or typeof x === undefined, etc, but what if we use the Miller Device?

An example of usage:

var myArray = [];

if(Object.prototype.toString.apply(myArray) === '[object Array]') {
  // do array operations
}

Every browser gives consistent results for JavaScript’s other top level objects:

object = [object Object]
array = [object Array]
string = [object String]
number = [object Number]
NaN = [object Number]
Infinity = [object Number]
function = [object Function]
boolean = [object Boolean]
date = [object Date]
regex = [object RegExp]
error = [object Error]

Testing for null and undefined is a bit more interesting:

Firefox, Opera:

null = [object Window]
undefined = [object Window]

IE 6-8:

null = [object Object]
undefined = [object Object]

Safari:

null = [object DOMWindow]
undefined = [object DOMWindow]

Chrome/V8:

null = [object builtins]
undefined = [object builtins]

Spidermonkey console:

null = [object global]
undefined = [object global]

In each case besides IE and Chrome, the string representation of the global object is being returned. IE returns the uninteresting [object Object] string, and Chrome hints again at why it should be distinguished from Safari, at least when testing JavaScript, by returning [object builtins].

If you were to use The Miller Device to detect null or undefined, you would simply use it on both the left and right sides of the comparison:

if( Object.prototype.toString.apply( MyObject ) ===
    Object.prototype.toString.apply( null ) ) {
  // FAIL
}

jsUnity

I was looking for a lightwieght, context-agnostic testing framework for JavaScript so I could describe the behavior of whatever script I was writing (and found one, thanks to Ates making it.) The particular script I was working on had no need for a browser or any of the extra environmental cruft - it was pure JavaScript, ready to be plugged in wherever it may go. Or perhaps it will never leave the comfort of a Spidermonkey shell, the point is I just wanted a quick run-down of what it should do, and not have to launch a browser just to see.

JavaScript decoupled from HTML? It is rare indeed. Even with server-side JavaScript you could still be dealing with a document.

Enter jsUnity (nice pun, by the way,) which lets you plug your test suite into any environment. You just supply a custom jsUnity.log function for logging to that environment.

jsUnity.log = function (s) { document.write(s + "</br>"); };

This rubs me the right way. This concept could be extended to allow other customizations for specific environments. The core test suite can stay light while modules are built around it.

The globally scoped assertions kind of bug me, but seem to be modeled after JsUnit style tests. Ideally, those assertions could reside in a module, making them as easy to use and safe to extend.

It’s a start, a nod in the right direction. Plus, there’s always github for forking.

Hey, JavaScript and HTML are a couple for now, but the way HTML has been flirting around, you never know… JavaScript needs to keep it’s figure right and assets in order - mmhm.

Odd: Using prototype as a Singleton

I was perusing the JsUnit code examples and noticed how they used the object’s prototype as a singleton:

var result = TextTestRunner.prototype.main( args );
JsUtil.prototype.quit( result );

Code like this appears throughout the page!

This strikes me with much fear and confusion. Surely, for use as a singleton, any arbitrary property name would be more appropriate than prototype, the home of instance method and property definitions. Why use a secondary namespace instead of the object itself, anyway?

The code base is old, so maybe conventions were not as strong then (though this seems largely fundamental,) or something was lost in translation.

In any case, I’m still looking for a good testing framework to use on the console, or in arbitrary contexts. Edit: found one.

jsonip, retrieve the client’s IP address via JSONP

This question on Stackoverflow spurred me to write my first Google App Engine project and consequently my first Python script, jsonip. It lets you retrieve a client’s IP address without needing your own server-side script. Normally you could make a call to a local server script that prints the user’s IP address then use an XMLHttpRequest to retrieve it. jsonip uses JSONP, so you could use it in a situation where you don’t have server-side processing available. The usage is simple enough:

Here’s the source code for the Python script: (When I say this was my first Python script, I mean it! I had to ask Google how to write if..then statements… )