Wednesday, January 28th, 2009

Xccessors: Cross browser JavaScript get/setters

Category: JavaScript

<p>Elijah Grey has created a shim called Xccessors that “is a script that implements the legacy methods for defining and looking up object accessors (getters and setters) of objects in JavaScript using ECMAScript 3.1’s accessors standard. This is aimed at adding support for the legacy method in IE8 RC1.”

You can check out a demo of it working, and told us a little more:

Note: IE8 RC1 does NOT support setting accessors on objects that are not instances of Window, Element (and all of it’s sub-classes), and HTMLDocument. I hope IE8 RC2 or the IE8 final public release changes this.

By not introducing any objects into the global namespace, the resulting code seems a little redundant, but not polluting the global namespace is worth an extra .4kb (the code is ~2kb uncompressed).
Also, as far as I know, it is impossible to do this the other way around and fully implement ECMAScript 3.1 accessor support in browsers that support the legacy method. Setting an object prototype that adds setters for <object>.[gs]etter can’t tell what the parent object of [gs]etter is unless it’s an element. It would be possible to partially implement Object.defineProperty and fully implement Object.getOwnPropertyDescriptor but many of the options that can be used in Object.defineProperty like writable and configurable would be hard to implement and enforce.

Posted by Dion Almaer at 4:03 am
8 Comments

+++--
3.7 rating from 13 votes

8 Comments »

Comments feed TrackBack URI

Quote from: http://msdn.microsoft.com/en-us/library/dd229916(VS.85).aspx

“We plan to expand accessor support for custom and built-in JavaScript objects, constructors, and prototypes in a future release.”

Will the inconsistencies in browsers ever go away? It’s seeming that once the new generation of browsers settle down that there will be more cross-browser coding required (XHR/XDomainRequest, accessors, canvas/SVG… etc). The immediate future for JS libraries seems to be safe from the cross-browser coding point of view.

Comment by RoryH — January 28, 2009

Sounds daft (and a bit of a tangent), but instead of worrying about the kb of one bloody js lib, why don’t people just say compress their images a tad? Most of the readers of Ajaxian won’t be guilty, just the monsters like facebook and mySpace…. Daft sods. On topic, this is a nice bit of coding! Good work!

Comment by oopstudios — January 28, 2009

@oopstudios
Shorter code also executes faster. This is especially true for interpreted languages…

Comment by ThomasHansen — January 28, 2009

I’m just excited to find another Elijah in the tech field :) LOL

http://twitter.com/elijahmanor
http://zi.ma/webdev

Comment by elijahmanor — January 28, 2009

@thomas
I would agree that if the code can be made shorter without losing any functionality (or re-usability), shorten it. However, oops might have been pointing out that heated discussions over 10k vs 6k are usually held between people with little to add to the discussion, often the same people that miss the 100k of logo and chrome images. On a slight tangent of my own, I still have production code that uses Behaviour.js, and do you know what? Nobody notices that the selector being used by the interface is probably the slowest one out there. That’s because milliseconds are very small slices of time. If you have followed the discussion around why sizzle doesn’t do document ordering (Resig is worried about losing the slickspeed war) you’ll see that oops isn’t wrong to be worried about where our collective head is at.

Comment by nataxia — January 28, 2009

A more compact implementation…?

(function() {
var x = function (a, b, f) {
if (a in Object && b in self) Object.prototype[b] = Element.prototype[b] = Window.prototype[b] = HTMLDocument.prototype[b] = f;
};
x('defineProperty', '__defineGetter__', function (prop, fun) {
Object.defineProperty(this, prop, { get: fun });
});
x('defineProperty', '__defineSetter__', function (prop, fun) {
Object.defineProperty(this, prop, { set: fun });
});
x('getOwnPropertyDescriptor', '__lookupGetter__', function (prop) {
return Object.getOwnPropertyDescriptor(this, prop).get
|| Object.getOwnPropertyDescriptor(this.constructor.prototype, prop).get;
});
x('getOwnPropertyDescriptor', '__lookupSetter__', function (prop) {
return Object.getOwnPropertyDescriptor(this, prop).set
|| Object.getOwnPropertyDescriptor(this.constructor.prototype, prop).set;
});
})();

Comment by broofa — January 28, 2009

@broofa: Good idea, using an anonymous function would definitely be the best solution.

Comment by EliGrey — January 29, 2009

Update: Implemented something similar to what @broofa recommended so script is now only around 700kb.

Comment by EliGrey — January 29, 2009

Leave a comment

You must be logged in to post a comment.