On Fri, Sep 30, 2011 at 9:50 AM, Xavier MONTILLET <[email protected]>wrote:
> Hi, > > I've been playing with getters and setters for a little while and > there's one thing really bothering me: You can't store the value in > the object in a hidden way. Here is an example: > > http://jsfiddle.net/xavierm02/UzNK3/13/ > > function Point( x, y ) { > this.x = x; > this.y = y; > } > Object.defineProperties( Point.prototype, { > x: { > get: function ( ) { > // this would return the stored value > }, > set: function ( value ) { > value = parseInt( value ); > // and here, you would want to set "this.x" to value but > you can't since this would create an infinite loop > } > }, > y: { > // same here > } > } ); > > You could do it by: > > - using Object.defineProperties in the constructor and therefore but > then, you would have several times the same function created so it > kinda sucks. > > http://jsfiddle.net/xavierm02/UzNK3/14/ > > function Point( x, y ) { > Object.defineProperties( Point.prototype, { > x: { > get: function ( ) { > return x; > }, > set: function ( value ) { > x = parseInt( value, 10 ); > } > }, > y: { > // same here > } > } ); > } > > - have some kind of array where you store values and another array > where you store the this and let those arrays be accessible only from > the methods needing it. Then you would get the index of the instance > by doing indexOf( this ) on the array of instances and then you would > search for the value at this index. Sucks too. > > http://jsfiddle.net/xavierm02/UzNK3/15/ > > ( function ( ) { > var instances = [ ], > xs = [ ], > ys = [ ]; > function Point( x, y ) { > instances.push( this ); > xs.push( x ); > ys.push( y ); > } > Object.defineProperties( Point.prototype, { > x: { > get: function ( ) { > return xs[ instances.indexOf( this ) ]; > }, > set: function ( value ) { > xs[ instances.indexOf( this ) ] = parseInt( value ); > } > }, > y: { > // same here > } > } ); > this.Point = Point; > } )( ); > > I don't know know what you think of this but these methods really > aren't convenient from my point of view... > > There are potential new features that could allow you to do this too: > > - private properties but then that would mean giving access to private > properties to the methods in the prototype, which would mean that > adding a method in the prototype would allow to change the values, > which isn't what you want... Even though you could freeze the > prototype to avoid it... > - I remember thinking of another one but I can't remember which one atm... > > So here'swhat I propose: > - the getter gets a parameter which is the stored value > - the setter's return value is set as value for the "private" property > > Here's an implementation of what I would like having (It sucks sinces > it prevents garbage collecting and could easilly be optimized but > still works): > > http://jsfiddle.net/xavierm02/UzNK3/17/ > > Object.defineProperties = ( function ( ) { > var defineProperties = Object.defineProperties; > return function ( object, propertyDescriptors ) { > for ( var name in propertyDescriptors ) { > if ( propertyDescriptors.hasOwnProperty( name ) ) { > ( function ( propertyDescriptor ) { > var get; > var set; > if ( propertyDescriptor.hasOwnProperty( 'get' ) ) { > get = propertyDescriptor.get; > propertyDescriptor.get = function ( ) { > return get.call( this, propertyDescriptor.value > ); > }; > } > if ( propertyDescriptor.hasOwnProperty( 'set' ) ) { > set = propertyDescriptor.set; > propertyDescriptor.set = function ( value ) { > return propertyDescriptor.value = > set.call( this, value ); > }; > } > } )( propertyDescriptors[ name ] ); > } > } > defineProperties( object, propertyDescriptors ); > }; > } )( ); > > And you would use it that way: > > http://jsfiddle.net/xavierm02/UzNK3/17/ > > function Point( x, y ) { > this.x = x; > this.y = y; > } > Object.defineProperties( Point.prototype, { > x: { > get: function ( value ) { > return value; > }, > set: function ( value ) { > value = parseInt( value ); > return value; > } > }, > y: { > // same here > } > } ); > > Of course, if it were implemented, it would probably allow setting a > defaut setter that woudl simply assign and a a default getter that > would simply return the value by putting true instead of the function. > Or somthing similar. > > Of course, for this example, implementing type checking would make it > useless. > But that really was just a example. Something where it would have a > real use is, for example: > > http://jsfiddle.net/xavierm02/UzNK3/20/ > > // isn't suposed to work > // here just for wyntax coloration > function WYSIWYGEditor( ) { > Object.defineProperties( this, { > iframe: { > value: document.createElement( 'iframe' ), > configurable: false, > enumerable: true, > writable: false > }, > textarea: { > value: document.createElement( 'textarea' ), > configurable: false, > enumerable: true, > writable: false > }, > container: { > value: document.createElement( 'div' ), > configurable: false, > enumerable: true, > writable: false > } > } ); > Object.defineProperty( this, 'wysiwygField', { > value: this.iframe./* get the container */, > configurable: false, > enumerable: true, > writable: false > } ) > this.container.appendChild( iframe ); > } > Object.defineProperties( WYSIWYGEditor.prototype, { > wysiwyg: { > value: true, > configurable: false, > enumerable: true, > get: function ( value ) {// or simply true or somethign > similar is shorcuts are implemented > return value > }, > set: function ( value ) { > value = !!value; > if ( value ) { > this.wysiwygField.innerHTML = this.textarea.value; > this.container.removeChild( this.textarea ); > this.container.appendChild( this.iframe ); > } else { > this.textarea.value = this.wysiwygField.innerHTML; > this.container.removeChild( this.iframe ); > this.container.appendChild( this.textarea ); > } > return value; > } > } > } ); > > What do you think? > See: http://wiki.ecmascript.org/doku.php?id=harmony:private_name_objects
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

