views:

70

answers:

4

I would like to have some sort of lazy initialied object properties in javascript and would thus want to somehow overload the property read and write access i.e.:

var someval = myobj.lazyprop; // invokes myobj.get("lazyprop");
myobj.lazyprop = someval;     // invokes myobj.set("lazyprop",someval);

where myobj is some object I provide to the script.

Rationale: I want to use Javascript (Rhino) as scripting engine in an application and the datastructures that need to be accessible by the scripts can be very large and complex. So I don't want to wrap them all in advance to javascript objects, esp. since the average script in this application will only need a very small subset of them. On the other hand I want the scripts to be as simple and readable as possible, so I don't want to require the use of get or set methods with string arguments explicitly in the scripts.

+1  A: 

I think this is something you should do using the Rhino-specific API from the Java side; not from Javascript.

Nicolás
I was investigating this already but the Rhino engine as it is included in the J2SE 1.6 JDK only exposes as faint language agnostic external API and the access control of the JVM forbids the use of it's internal classes. To use the original Mozilla Rhino is also not an option for me.
x4u
I didn't say it wasn't a Javascript feature. I said it was better to do it from the Java side. But I'll clarify.
Nicolás
+2  A: 

many js engines support getters and setters on javascript objects:

var obj = {
  get field() {alert('getting field');}
  set field(val) {alert('setting field to ' + val);}
}

var x = obj.field     // alert pops up
obj.field = 'hello'   // alert pops up

more details:

http://robertnyman.com/2009/05/28/getters-and-setters-with-javascript-code-samples-and-demos/

jspcal
That syntax is superdeprecated.
Nicolás
it's not deprecated at all. this style was *just added* in ECMAScript 5 - the *latest* version of javascript
jspcal
@jspcal: you're right - didn't know that Oo; check ECMA-262, 5th edition, eg section 11.1.5
Christoph
Just for the record, **never** have a property (getter or setter) that generates an user response outside debugging/development. That's what functions/methods are for.
voyager
@voyager: false, getters/setters *are functions* and can be used for *anything* a traditional function can. (you should learn about `window.location.href` which is a property that can generate messages and has since the early days of js)
jspcal
+2  A: 

You can do it using Rhino 1.6R6 or higher with javascript getters and setters.

function Field(val){
   var value = val;

   this.__defineGetter__("value", function(){
       return value;
   });

   this.__defineSetter__("value", function(val){
       value = val;
   });

}

Now, if we wanted to, instead, define getters and setters within the context of our object prototype (and where having "private" data is less of a concern) we can then use an alternative object syntax for that.

function Field(val){
   this.value = val;

}

Field.prototype = {
   get value(){
       return this._value;
   },
   set value(val){
       this._value = val;
   }

};

voyager
jspcal
also you should've noted that according to the mozilla docs, the first form (using "__defineGetter__): "can make the code hard to read and understand." while the style in my post is recommended as "more compact and natural."
jspcal
*can make the code hard to read and understand* is subjective. I find it rather nice, but I code in Python and the underlying system is exactly the same, only that you have a `property` function. Also, the use of `__defineGetter__`/`__defineSetter__` is useful when you need to override an existing getter/setter, as they silently overwrite the previous getter/setter, whereas with the other syntax, you have to delete the existing one first. I really don't know what more you'd like me to add beyond the quoted text and the attribution link. There is no more explanation needed for the question IMO
voyager
without reading the links, it's impossible to know that is a long paste copied from another site because you never state it as being a quote. it's easy to assume you are just highlighting some text. you should state explicitly where you got it from, something like: `from "JavaScript Getters and Setters:"` or "according to John Resig". if you don't know why this is important, read any academic handbook.
jspcal
@jspcal: there is a reason all that text is in a `blockquote` tag immediately after a link.
voyager
+2  A: 

Rhino versions > 1.6R6 support getters and setters, you could write something like this:

var myobj = {
  // a getter and setter
  get lazyprop(){ return this.get('lazyprop'); },
  set lazyprop(val){ return this.set('lazyprop', val); },

  // the logic of your get and set methods:
  get: function(p) { return this['_'+p]; },
  set: function(p, val) { this['_'+p] = val; }
};
CMS