Please, please implement getters and setters in your JavaScript engine. I cannot tell you how much I want to add this to JS.Class:
var MagicMethods = {
included: function(klass) {
var define = function(object, name) {
var shortName = name.replace(/^[gs]et[A-Z]/,
function(s) { return s.charAt(3).toLowerCase() });
if (/^get[A-Z]/.test(name))
object.__defineGetter__(shortName,
function() { return this[name]() });
if (/^set[A-Z]/.test(name))
object.__defineSetter__(shortName,
function(value) { return this[name](value) });
};
for (var key in klass.prototype)
define(klass.prototype, key);
if (klass.instanceMethod)
klass.instanceMethod = (function(wrapped) {
return function() {
var name = arguments[0];
define(klass.prototype, name);
return wrapped.apply(klass, arguments);
};
})(klass.instanceMethod);
}
};
This mixin needs a few type checks adding but I didn’t want to obscure the main
idea. When mixed into a class, MagicMethods
will intercept all instance method
definitions and, if the method name looks like getX
or setX
it will add a
shorthand getter or setter to the class. So, for example, the main collection
class in Ojay has a bunch of methods like setStyle
, getRegion
and
what-not. If we use the above mixin, we can get more intuitive code:
Ojay.DomCollection.include(MagicMethods);
// Set style of all paras
$('p').setStyle({fontStyle: 'italic'}); // old
$('p').style = {fontStyle: 'italic'}; // new
// Find region of the title
var region = $('h1').getRegion(); // old
var region = $('h1').region; // new
Granted, I’m not saving a huge amount of typing here, but getters and setters
get you out of the trap of having to make everything a method rather than a
property to enforce encapsulation. style=
and region
in the above code look
like property accesses, but are really function calls to setStyle()
and
getRegion()
under the covers. You can implement something as a property to
begin with, then later on you can change it to a getter method without breaking
anyone’s code. It really comes into its own when using MethodChain
:
MagicMethods.included(JS.MethodChain);
$('p').on('mouseover').style = {color: 'red'};
$('a').on('click', $.stopDefault).content = 'Clicked!'
This makes for a more declarative style for doing simpe event handling.
Anyways, this is all a moot point because this technique only works in Firefox and Safari. If we’re going to count beta versions, Opera 9.5 supports it too (thanks to John Resig for the heads-up). I’ve no idea whether IE8 plans to support it, and I don’t think it’s in the ECMAScript standard (3 or 4) so they’ve really no obligation to (comments proving me wrong greatly appreciated). In any case, the need to support IE 6 and 7 for the foreseeable future means I can’t use this feature, and I’m pretty sure there’s no way to reliably fake it in IE. Any ideas on 3-by-5 cards, please.