### Answer to Bemi Faison ### > I'm definitely late to this thread, but isn't this what the ES5 Proxy object > is all about? Didn't know that thing existed O_O But it doesn't see like finished... I'll digg into it and see if I can make my API so that it is possible to get from one to the other. This way I would allow writing code with that API and it would be compiled to my API so that old browsers get it. But I hope it won't be as slow as native getters / setters... http://jsperf.com/native-getters-vs-function-getters/3
> Even the ES5 Object constructor lets you handle non-mapped properties. I didn't understand what you mean by non-mapped... You mean having a default getter? > Also, JavaScript 1.8.1 (available since FireFox 3.5) lets you define getters > and setters for properties - such that assignments (via "=") actually pass > arguments to an internal setter function. It's slow... And can't be emulated on IE. > Without these, you would need to use closures and use an access schema within > your get/set functions. The caveat with this non-native approach, is that > developers would need to learn your table schema, or the API for defining it > (as you have already). If I'm off, then pardon me and continue your > discussion... My API isn't that hard :o > If I'm right, then check out my previous work, GSet, at > https://github.com/bemson/GSet/ . (It was formally called Proxy, until I > discovered the ES5 Proxy object.) My approach differs from yours, in that my > object is compiled (i.e., cannot be changed). XJSAccessors.js lets the > developer change the access scheme of an object dynamically. Thus, I use a > configuration object, while you have an API. On the subject of what to name > getters and setters, I chose to follow jQuery's same-name approach. Well I prefer mine :-* And I don't like the jQuery approach for getters / setters because having the same function as getters and setter seems strange to me. You have to do the exact same condition in every single function... and you can't have a default setter / getter. > One last note: I'm phasing out my own use of GSet, as it's numerous closures > actually degrade performance. Obviously but unless you loop on the object, i can't be that much. You just need to store the value in a local variable when using the object from outside. And I'm thinking of "compiling" my code so that for "public" (with no getter or setter and not readonly / protected) properties, it gets back to the normal thing. But I'll see that later. I want my code to work as is. If i can be compiled to be faster, why not :) On Fri, Sep 2, 2011 at 2:09 PM, Xavier MONTILLET <[email protected]> wrote: > ### Answer to Scott Sauyet ### > >> If my object is a dumb data container with no behavior, then I probably want >> direct access to its properties > Well the syntax is a bit longer but you have, kind of, direct access... > >> Perhaps I don't care if it's calculated, read-only, or normal. But perhaps >> I do. > I don't see any cases where you want to know whether it is calculated or > not... > >> I certainly don't want to have to wrap a try-catch around setting the >> property on the off-chance it might be read-only. > - When you build your API: As the thing that lets you change getters / > setters is local to the constructor, it can't be used by other code > (except if you don't get the point at all and expose it...) so as you > decide what is readonly and what is not. > - When you use an API: You'll use a property and if you get an error, > it'll be during development. I thought about failing silently but > then, you wouldn't know if your value was set or not. Here, you know > either it is set or you get an error because it is readonly. I mean as > it is either readonly or not but won't change, you know that if you > get the error you will never be allowed to write... I'm not sure I' > clear. Please tell me if I am not. > >> And I don't want to have to do a for-in just to find out what features my >> object supports, at least not when its design is something already in my >> control. > Well that's what the documentation is for... If you have a "normal" > object, you get to for in it to see what's in... > E.g.: PhantomJS. This thing is awesome but the documentation sucks. > Well I used for in of the page object and the phantom object to see > what properties I had... even though they use a "normal" API. > >> There are new language features creeping in that will allow us to do >> C#-style setters and getters, but I've almost never had a need for them in >> Javascript. > Well the first thing is native getters are way too slow: > http://jsperf.com/native-getters-vs-function-getters/3 > Plus they don't work in IE. > And there is nothing to get any property. > If you want to emulate an array, you can't or you would need to set > getters and setters for 0, 1, 2, 3, 4... > There is no such thing as object.__defineGetter__( '*', f ); In fact > this works but for the '*' property... whereas you would want it to be > the getter for all properties you don't know. I'm planning on > implementing that too in my getters / setters: A default getter / > setter. > >>But I simply can't see the advantage of turning this: >> >> myRectangle.height = 3; >> myRectangle.width = 5; >> var area = myRectangle.getArea(); >> >>into this: >> >> myRectancle.set("height", 3"); >> myRectancle.set("width", 3"); >> var area = myRectangle.get("area"); >> >>I can't even buy that the latter would be better than >> >> myRectangle.setHeight(3); >> myRectangle.setWidth (5); >> var area = myRectangle.getArea(); > For the first code, the problem is you need to know what property can > only be set by a function and what property can be set "normaly". > For the third code, the problem is that cycling though the object is a > pain (it is in first too) and if you want to implement a default > getter / setter, you can't use that syntax. Plus for some reason, I > don't like it. > >> Have you thought through how you might document your API? I love tools like >> JSDoc, but can't see how to use anything like it with your code. Do you >> have other ideas? > Well in fact, you can use any tool... You just need to put a page that > explains how the API works and let the others that describe properties > as they are. > But that won't come before I judge my code is "usable". > >> I'm not sure it's a matter of caring. It's a matter of what facilities the >> language provides, and what glosses you are trying to provide. You seem to >> be promoting something that to me makes it less clear what's going on. I >> understand that you don't see it that way, but having an object with only >> three properties, the functions `get`, `set`, and `forIn` just confuses >> things for me. > > Well just think as if o.set( 'p', 'v' ) was o.p = 'v' and o.get( 'p' ) was o.p > And o.forIn( function ( name ) { } ) is for ( var name in o ) {} > I might also update set to accept this syntax: > > o.set( { > p: 'v', > p2: 'v2' > } ); > >> When myRectangle has numeric properties `height` and `width` and a function >> `getArea`, I have a pretty good idea how to use it. If myRectangle exposes >> `get`, `set`, and `forIn`, which is the same API exposed by mySpaceship and >> myHttpRequest, I'm really not certain how to use any of them. > Except for that one time with PhantomJS, I never looked directly the > API on the object... everything has a documentation... > But I could also add a getAll method on the object that uses the forIn > to loop through all properties and creates a new object containing all > the values it got. It would let you explore it easily. > >>I don't think it's that they don't care what it does, but that they don't >>care how it does it. But speaking of jQuery, could you imagine a version of >>it using your Accessors? What would it look like for a jQuery wrapped >>object? How would the `.data()` function be structured? How about >>`.addClass()` or `.attr()`? Or it's not a candidate for using your tool, >>what would distinguish a good candidate? > > new XJSElement( element ).get( 'data' ).set( 'property', 'value' ); > XJSElement could be replaced by jQuery if jQuery was building the good > methods. > > new XJSElement( element ).get( 'class' ).set( 'property', 'value' ); > > new XJSElement( element ).get( 'attributes' ).set( 'src', 'w/e' ); > > But of course, you'll also be able to do that: > new XJSElement( element ).get( ['attributes', 'src'] ); > Or event > new XJSElement( element ).get( 'attributes', 'src' ); > or > new XJSElement( element ).get( 'attributes.src' ); > But I'm sot sure about the last one because it disallows getting > properties whose name contain a point. I've never seen one though. > And the one before would disallow passing arguments to getters. > > It might look a bit long but if you provide a direct data property: > new XJSElement( element ).data > it mean you have already built a new instance of the XJSElementData > constructor and if it is bot used, you lost time. > > Another approch would be wrappers / aliases: > new XJSElement( element ).get( 'data', 'name' ); > new XJSElement( element ).set( 'data', 'name', 'value' ); > Because as you have seen, the getters get all the arguments passed to > get so they can use some. > for the getters that would be simple. For the setters, I have to do > some "router" that will know how many times to use get before using > set (It might be when it has 2 arguments left but then, composite > values for setters, i mean setters that get more arguments wouldn't > work. Same for setters allowing to not define the value and set > something if it is undefined. ). We'll see. > >> That's what I suspected. I'm curious about the environment you're using >> this sort of code in? It reminds me a bit of the JavaBeans spec -- great >> for tooling and other applications where the consumer knew nothing about >> your API but just an additional burden for direct consumers who are using >> your API semantically. > Well I never used something like that... In fact I only know HTML, > CSS, JS, a bit of PHP and the minimum of Python. And shell. > And I don't see how it could be a burden (except that it's a bit > longer to write...) > > > On Thu, Sep 1, 2011 at 7:47 PM, Bemi Faison <[email protected]> wrote: >> I'm definitely late to this thread, but isn't this what the ES5 Proxy object >> is all about? Even the ES5 Object constructor lets you handle non-mapped >> properties. Also, JavaScript 1.8.1 (available since FireFox 3.5) lets you >> define getters and setters for properties - such that assignments (via "=") >> actually pass arguments to an internal setter function. >> Without these, you would need to use closures and use an access schema >> within your get/set functions. The caveat with this non-native approach, is >> that developers would need to learn your table schema, or the API for >> defining it (as you have already). If I'm off, then pardon me and continue >> your discussion... >> If I'm right, then check out my previous work, GSet, at >> https://github.com/bemson/GSet/. (It was formally called Proxy, until I >> discovered the ES5 Proxy object.) My approach differs from yours, in that my >> object is compiled (i.e., cannot be changed). XJSAccessors.js lets the >> developer change the access scheme of an object dynamically. Thus, I use a >> configuration object, while you have an API. On the subject of what to name >> getters and setters, I chose to follow jQuery's same-name approach. >> As an example, here's how you would use GSet to configure getters, setters, >> and "calculators". >> /example------------------------------ >> var mySquare = new GSet( >> {myWidth:4, myLength:2}, // original/protected object >> { // access scheme >> width: ['myWidth', 'number'], >> length: ['myLength', 'number'], >> area: [ >> function () { >> return this.myWidth * this.myLength; >> }, >> 'number', >> function (w, l) { >> if (arguments.length > 1) { >> this.myWidth = w; >> this.myLength = l; >> } else { >> return false; >> } >> } >> ] >> } >> ); >> mySquare.width(2); // true >> mySquare.width(); // 2 >> mySquare,width('foo'); // false >> mySquare.area(); // 4 >> mySquare.area(10,10); // true >> mySquare.area(); // 100 >> ------------------------------example/ >> One last note: I'm phasing out my own use of GSet, as it's numerous closures >> actually degrade performance. >> - best, >> bemson >> >> -- >> To view archived discussions from the original JSMentors Mailman list: >> http://www.mail-archive.com/[email protected]/ >> >> To search via a non-Google archive, visit here: >> http://www.mail-archive.com/[email protected]/ >> >> To unsubscribe from this group, send email to >> [email protected] >> > -- To view archived discussions from the original JSMentors Mailman list: http://www.mail-archive.com/[email protected]/ To search via a non-Google archive, visit here: http://www.mail-archive.com/[email protected]/ To unsubscribe from this group, send email to [email protected]
