Getter/Setter Properties in OO Javascript

I just asked a guru of advanced Object-Oriented Javascript, Douglas Crockford the following question.  For posterity, and for other possible takers, I’m posting it here too.


Also, for the record, this has nothing to do with IE’s proprietary — but wonderful — setExpression method or CSS expression capabilities.  Those dynamic properties only apply to DOM objects, not custom Javascript objects.






Do you know of a way to define dynamic object properties in Javascript?


For example, VBScript lets us define classes such as this:


CLASS myClass
PUBLIC phrase
PUBLIC PROPERTY GET firstword ‘get first word from phrase
firstword = left(phrase, instr(phrase, ” “))
END PROPERTY
PUBLIC PROPERTY LET firstword(v) ‘set phrase’s new first word
phrase = v & ” ” & phrase
END PROPERTY
END CLASS

This demonstrates two important features:
1. the firstword property can return dynamic results (depending on the current value of the phrase property). 
2. setting the firstword property can run other code (which dynamically prepends to the phrase property).


We can fully accomplish #1 (Property Get) in Javascript, by reassigning the toString method/property to a function like so:


function myConstructor(){
var self = this; //preserve object’s context
this.phrase = ”;
this.firstword = function(v){
if(v){self.phrase = v + ‘ ‘ + self.phrase}; //LET
return self.phrase.substring(0, self.phrase.indexOf(‘ ‘)); //GET
}
this.firstword.toString = this.firstword;
}

…But I’ve found no way to achieve #2 (Property Let or Set) in Javascript.  I can set firstword as a method, but setting the property value overwrites the method definition (and all subsequent GETs return that static value).


I’ve extensively searched, but found no answer (at least not before Javascript 2.0, which doesn’t yet exist).  Any ideas from the experts?

Update: Douglas Crockford responded that he doesn’t care for getter/setter properties, since “it allows simple assignment to have side effects, which I think works against reliability.”  (I take that as a “No, it’s not possible.”)
    My current need is that I’m patterning my custom object after part of the DOM, whose objects certainly do have getter/setters.  I agree with Douglas that getter/setter side effects can be dangerous (esp. in the hands of a poor coder, as with any powerful code construct), but I think the use of methods -vs- getter/setter properties should be in the realm of “best practice” rather than a language limitation. 

Bookmark the permalink.

6 Responses to Getter/Setter Properties in OO Javascript

  1. Chris Baker says:

    Can you provide an example of using #2. I’m trying to envision a need for it. I’ll confess to trying to avoid VBScript like the plague, although lately that has been impossible. The shop that I’m at had no idea that VBScript even supported OO.

    Personally the idea of class field accessors having side effects makes me nervous. I like my classes to be such that every field has a getter that gets and a setter that sets and nothing else (JavaBeans style). Any kind of programatic stuff is done through seperate well documented methods. I know that Perl cat get more contextual but that always makes me nervous. This is especially true for classes that I dub data objects. I like them to be real tight. If you’re sure of the quality of your data, you can relax a lot more with classes that play with it.

    BTW, I agree with you about getter/setter methods. For me they are the Class’s contract police insuring that what goes in is valid and in some cases saving memory by only instantiating portions of the Object when needed in getters. But this is all coming from being a Java type.

    BTW, found your blog through http://www.feedmap.net/blogmap/neighblogs.aspx?feed=http://blog.cbaker.org/wp-atom.php . Heynow!

  2. Rob Eberhardt says:

    Regarding #2:
    I mentioned “My current need is that I’m patterning a custom object after part of the DOM, whose objects certainly do have getter/setters.”
    To explain: I’m working on a wrapper object which exposes an checkboxes/radio button arrays in a similar manner to a SELECT object’s options. For example, SELECTs have directly-accessible selectedIndex and value properties. To get the equivalent info with radio buttons normally requires looping script. Another common checkbox/radio button operation I wanted to simplify is that of assigning event handlers (again without custom looping code).

    Yes, I can write a reusable function to accomplish these (and have), but I wanted to wrap it all up into a single convenient object instantiation. Besides less code, it would also make it easier to switch "glue code" between SELECTs and checkbox/radio button arrays (which are interchangeable from a UI standpoint).

    Native SELECT and other DOM objects DO support setter properties, so I wanted to do the same for consistency. Otherwise, I wouldn’t normally create setter properties in Javascript, opting instead for set methods. I have it partially working (gets but not sets).

    It disappoints me that Javascript, an astonishingly powerful OO scripting language, loses to simple old VBScript in a matter like this (dates too, but that’s another story).

    Cool about the Feedmap link (that got me to waste a lotta time!). For some reason I had the wrong ICBM coords, so it thought I was in Warren County.

    Don’t miss GeoURL either: http://geourl.org/near?p=http://throbs.net/

  3. Jonathan Watt says:

    Mozilla supports ES4 getters and setters, but as you say, that’s a work in progress.

    function myConstructor(phrase) {
    this.phrase = phrase;
    }
    myConstructor.prototype = {
    get firstword() {
    return this.phrase.substring(0, this.phrase.indexOf(‘ ‘));
    },
    set firstword(word) {
    this.phrase = word + ‘ ‘ + this.phrase;
    }
    }
    var obj = new myConstructor(‘hello world’);
    alert(obj.firstword);

  4. Rob says:

    That’s great, thanks Jonathan.

    Indeed, adding this works in Firefox as I would hope:
    obj.firstword = ‘hi';
    alert(obj.firstword); // alerts ‘hi’ (without overwriting)

    I hadn’t realized that was implemented yet in Mozilla/Firefox. Very cool!

  5. Nathan Bird says:

    I talk about this a bit here: <a target="_new" href="http://blogs.acceleration.net/birdman/archive/2005/04/28/1055.aspx">http://blogs.acceleration.net/birdman/archive/2005/04/28/1055.aspx</a&gt;

    Jonathan Watt demonstrated one way above, there is another way as well:
    var o = {i:0} //declare object
    //add a getter property at ‘foo’
    o.foo getter = function() {this.i++; return &quot;foo&quot; + i; }
    o.foo //returns “foo1″, “foo2″ ….

    Drawbacks:
    *This only works in Mozilla.
    *I have not been able to find a way to get a reference to that getter/setter function. Any time you try to access it you just get the evaluated value. If you needed to pass the function into another function or wish to inspect the function source you seem to be out of luck.

    On Doug Crawford’s note:
    I agree with Rob that this should be more a matter of good practice: don’t do anything unexpected for the external programmer like return a different value from the setter function than one that was passed in.
    o.foo = o.bar = “foobar”; // o.foo should be set to the value “foobar” regardless of whether o.bar is data slot or a property.

  6. Milagro says:

    I’d really love to see a way for the gerttes and setters to be placed together at near the top. Just an organizational thing I have, probably from not using an IDE before and therefor no declaration detection.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>