Re: Setting a property in the prototype chain?
On Tue, Apr 12, 2011 at 08:41, Allen Wirfs-Brock wrote: > In ES5 > {}.valueOf.call(undefined) > doesn't yield the this object. In general, ES5 built-ins do not convert their > this parameter to the global object when it is undefined. FYI http://code.google.com/p/v8/issues/detail?id=1321 https://bugs.webkit.org/show_bug.cgi?id=58338 -- erik ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
On Apr 12, 2011, at 12:57 AM, Lasse Reichstein wrote: > > In that case, why not just > obj = Object(obj); > > It has the added advantage of not returning the global object for null and > undefined, > but just a plain new object (although either can be said to be wrong in this > case). I used {}.valueOf in order to avoid converting null and undefined to a new object which would then be used as the starting point of the lookup. In ES5 {}.valueOf.call(undefined) doesn't yield the this object. In general, ES5 built-ins do not convert their this parameter to the global object when it is undefined. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
On Tue, Apr 12, 2011 at 3:57 AM, Lasse Reichstein < reichsteinatw...@gmail.com> wrote: > On Tue, 12 Apr 2011 07:55:26 +0200, Allen Wirfs-Brock < > al...@wirfs-brock.com> wrote: > > >> On Apr 11, 2011, at 6:45 PM, Axel Rauschmayer wrote: >> >> var obj={}.valueOf.call(obj); // ToObject in case primitive value passed >>> ... > > {}.valueOf is the same value as Object.prototype.valueOf assuming none of >> the standard definitions have been over-written. See the comment thread of >> http://www.wirfs-brock.com/allen/posts/166 for a debate as to which of >> these forms is more or less optimizable. >> >> Object.prototype.valueOf as specified is essentially a call to the >> internal ToObject operation that wrappers primitive values. I put it in to >> deal with cases like getDefiningObject("some string", "match") >> > > > In that case, why not just > obj = Object(obj); > > It has the added advantage of not returning the global object for null and > undefined, > For null and undefined, Object.prototype.valueOf throws. It does not return the global object. > but just a plain new object (although either can be said to be wrong in > this case). > > /L > -- > Lasse Reichstein - reichsteinatw...@gmail.com > > ___ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
> Object.prototype.valueOf as specified is essentially a call to the internal > ToObject operation that wrappers primitive values. I put it in to deal with > cases like getDefiningObject("some string", "match") Oh my, I've just consulted the ECMAScript spec and it's true. But isn't that counter-intuitive? - Object.prototype.valueOf: convert to object - String.prototype.valueOf: convert to primitive (for instances of String and primitive strings) - Number.prototype.valueOf: same as above, but for numbers - etc. Even if that can't be fixed any more, there could be a method Object.toObject() with more obvious semantics. I try to avoid "expert magic" when using a programming language and it seems like a shame that this kind of magic is necessary here ( {} and valueOf()). Greetings, Axel -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
On Tue, 12 Apr 2011 07:55:26 +0200, Allen Wirfs-Brock wrote: On Apr 11, 2011, at 6:45 PM, Axel Rauschmayer wrote: var obj={}.valueOf.call(obj); // ToObject in case primitive value passed ... {}.valueOf is the same value as Object.prototype.valueOf assuming none of the standard definitions have been over-written. See the comment thread of http://www.wirfs-brock.com/allen/posts/166 for a debate as to which of these forms is more or less optimizable. Object.prototype.valueOf as specified is essentially a call to the internal ToObject operation that wrappers primitive values. I put it in to deal with cases like getDefiningObject("some string", "match") In that case, why not just obj = Object(obj); It has the added advantage of not returning the global object for null and undefined, but just a plain new object (although either can be said to be wrong in this case). /L -- Lasse Reichstein - reichsteinatw...@gmail.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
On Apr 11, 2011, at 6:45 PM, Axel Rauschmayer wrote: >> var obj={}.valueOf.call(obj); // ToObject in case primitive value passed > > Can you explain how this works? > > - Why {} and not Object.prototype? > > - I know valueOf as a method that returns a primitive if an object can be > converted to one and |this|, otherwise. Oddly enough, this works both in > strict mode and in non-strict mode, as explained in the comment. > {}.valueOf is the same value as Object.prototype.valueOf assuming none of the standard definitions have been over-written. See the comment thread of http://www.wirfs-brock.com/allen/posts/166 for a debate as to which of these forms is more or less optimizable. Object.prototype.valueOf as specified is essentially a call to the internal ToObject operation that wrappers primitive values. I put it in to deal with cases like getDefiningObject("some string", "match") Allen___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
> var obj={}.valueOf.call(obj); // ToObject in case primitive value passed Can you explain how this works? - Why {} and not Object.prototype? - I know valueOf as a method that returns a primitive if an object can be converted to one and |this|, otherwise. Oddly enough, this works both in strict mode and in non-strict mode, as explained in the comment. Thanks! Axel -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
On Apr 11, 2011, at 9:21 PM, David Bruant wrote: > Actually I was wrong I think. With the introduction of proxies, ES > engines won't be able to trivially prevent pd allocation as they could > with regular objects just based on static analysis (since static > analysis will often fail at saying whether the function will be used > with regular objects or proxies as first argument) Static analysis is conservative, yes. But type inference often can say what exact types |this| and other arguments have. Anyway, this isn't about absolute guarantees unless JS provides an API to query without allocating :-P. > I think it could be possible if we had a native Object.hasOwnProperty > method since that's really what we need here (that's what a static > analysis optimization would do internally). That was left out on purposes during ES3.1/ES5 design to keep things minimal. And of course Proxies built on that API. So probably we should leave this as an optimization challenge (GC, type inference, both if possible). /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
Le 11/04/2011 22:01, Brendan Eich a écrit : > On Apr 11, 2011, at 8:58 PM, David Bruant wrote: > >> Le 11/04/2011 21:47, Brendan Eich a écrit : >>> On Apr 11, 2011, at 6:36 PM, Allen Wirfs-Brock wrote: >>> Personally, I prefer Object.getOwnPropertyDescriptor as a property existence test because it doesn't have the reflection the meta-circularity concern. I would write Dave's original function as: function getDefiningObject(obj, key) { var obj={}.valueOf.call(obj); // ToObject in case primitive value passed while (obj) { if (Object.getOwnPropertyDescriptor(obj,key)) return obj; obj = Object.getPrototypeOf(obj); } throw new Error("key " + key + " not found"); } >>> Then the only downside is the pd allocation. Any way to avoid that? >> Could static analysis help out to detect that the object is not going to >> be used and consequently avoid the allocation? > Of course, but that's a bit much and unless it is adopted by all the "bigs", > web developers won't count on it and may shy away from the allocation (based > on real measurements or premature optimization, doesn't matter). Actually I was wrong I think. With the introduction of proxies, ES engines won't be able to trivially prevent pd allocation as they could with regular objects just based on static analysis (since static analysis will often fail at saying whether the function will be used with regular objects or proxies as first argument) > It's not the end of the world to have a pd allocation, of course. But an API > that avoids it without analysis might be worth considering. I think it could be possible if we had a native Object.hasOwnProperty method since that's really what we need here (that's what a static analysis optimization would do internally). David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
On Apr 11, 2011, at 12:47 PM, Brendan Eich wrote: >> > > Then the only downside is the pd allocation. Any way to avoid that? > > /be Use a GC that supports cheap allocation/recovery of short-lived objects :-) It's probably premature optimization to worry about that one pd allocation without knowing more about the actual use case. I suspect that in many cases, the caller would actually want to get the pd back and so it would probably be best to return: {object: obj, desc: pd}. Of course that has yet another ephemeral object allocation. But really, if you over worry about such allocations you end up doing FORTRAN-like coding. Maybe it's time to work on some JavaScript ephemeral GC benchmarks... Allen___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
On Apr 11, 2011, at 8:58 PM, David Bruant wrote: > Le 11/04/2011 21:47, Brendan Eich a écrit : >> On Apr 11, 2011, at 6:36 PM, Allen Wirfs-Brock wrote: >> >>> Personally, I prefer Object.getOwnPropertyDescriptor as a property >>> existence test because it doesn't have the reflection the meta-circularity >>> concern. I would write Dave's original function as: >>> >>> function getDefiningObject(obj, key) { >>> var obj={}.valueOf.call(obj); // ToObject in case primitive value passed >>> while (obj) { >>> if (Object.getOwnPropertyDescriptor(obj,key)) return obj; >>> obj = Object.getPrototypeOf(obj); >>> } >>> throw new Error("key " + key + " not found"); >>> } >> Then the only downside is the pd allocation. Any way to avoid that? > Could static analysis help out to detect that the object is not going to > be used and consequently avoid the allocation? Of course, but that's a bit much and unless it is adopted by all the "bigs", web developers won't count on it and may shy away from the allocation (based on real measurements or premature optimization, doesn't matter). It's not the end of the world to have a pd allocation, of course. But an API that avoids it without analysis might be worth considering. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
Le 11/04/2011 21:47, Brendan Eich a écrit : > On Apr 11, 2011, at 6:36 PM, Allen Wirfs-Brock wrote: > >> Personally, I prefer Object.getOwnPropertyDescriptor as a property existence >> test because it doesn't have the reflection the meta-circularity concern. I >> would write Dave's original function as: >> >> function getDefiningObject(obj, key) { >> var obj={}.valueOf.call(obj); // ToObject in case primitive value passed >> while (obj) { >> if (Object.getOwnPropertyDescriptor(obj,key)) return obj; >> obj = Object.getPrototypeOf(obj); >> } >> throw new Error("key " + key + " not found"); >> } > Then the only downside is the pd allocation. Any way to avoid that? Could static analysis help out to detect that the object is not going to be used and consequently avoid the allocation? David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
On Apr 11, 2011, at 6:36 PM, Allen Wirfs-Brock wrote: > Personally, I prefer Object.getOwnPropertyDescriptor as a property existence > test because it doesn't have the reflection the meta-circularity concern. I > would write Dave's original function as: > > function getDefiningObject(obj, key) { > var obj={}.valueOf.call(obj); // ToObject in case primitive value passed > while (obj) { > if (Object.getOwnPropertyDescriptor(obj,key)) return obj; > obj = Object.getPrototypeOf(obj); > } > throw new Error("key " + key + " not found"); > } Then the only downside is the pd allocation. Any way to avoid that? /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
Personally, I prefer Object.getOwnPropertyDescriptor as a property existence test because it doesn't have the reflection the meta-circularity concern. I would write Dave's original function as: function getDefiningObject(obj, key) { var obj={}.valueOf.call(obj); // ToObject in case primitive value passed while (obj) { if (Object.getOwnPropertyDescriptor(obj,key)) return obj; obj = Object.getPrototypeOf(obj); } throw new Error("key " + key + " not found"); } ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
On 11/04/2011, at 05:14, Mark S. Miller wrote: > > On Apr 10, 2011, at 22:18 , David Herman wrote: > > > function getDefiningObject(obj, key) { > >if (!(key in obj)) > >throw new Error("key " + key + " not found"); > >while (!obj.hasOwnProperty(key)) > > That should be > > while (!{}.hasOwnProperty.call(obj, key)) > > which works even if obj has an own property named 'hasOwnProperty'. And also because that would work for null too, unlike (null).hasOwnProperty( key ) that would throw "TypeError: 'null' is not an object (evaluating '(null).hasOwnProperty')", and null is at the end of the prototype chain of all objects... Here's another take on it: function getDefiningObject (o, key) { do { if ( {}.hasOwnProperty.call(o, key) ) break; } while ( o = Object.getPrototypeOf(o) ); return o; } getDefiningObject([1,2], 'length') [1, 2] getDefiningObject([1,2], 'pop') [] getDefiningObject([1,2], 'valueOf') Object getDefiningObject([1,2], 'none') null -- Jorge. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
> Exactly what I was looking for. Thanks. > > Not exactly... True. But it's OK for me as a work-around. > That should be > > while (!{}.hasOwnProperty.call(obj, key)) > > which works even if obj has an own property named 'hasOwnProperty'. IIRC, {} creates a new instance for each invocation. Thus, a better solution would be while (!Object.prototype.hasOwnProperty.call(obj, key)) But I usually prefer David’s more readable version and take the risk of a name clash. -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
I wondered if someone was going to make this point. > That should be > > while (!{}.hasOwnProperty.call(obj, key)) > > which works even if obj has an own property named 'hasOwnProperty'. Not if someone mutates Object.prototype.hasOwnProperty or Function.prototype.call. I don't think we need to polish a proof of concept. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
On Sun, Apr 10, 2011 at 6:59 PM, Axel Rauschmayer wrote: > Exactly what I was looking for. Thanks. > Not exactly... > > On Apr 10, 2011, at 22:18 , David Herman wrote: > > > function getDefiningObject(obj, key) { > >if (!(key in obj)) > >throw new Error("key " + key + " not found"); > >while (!obj.hasOwnProperty(key)) > That should be while (!{}.hasOwnProperty.call(obj, key)) which works even if obj has an own property named 'hasOwnProperty'. > >obj = Object.getPrototypeOf(obj); > >return obj; > > } > > > > On Apr 10, 2011, at 10:24 AM, Axel Rauschmayer wrote: > > > >> As far as I am aware, there is no way to change a property that isn’t at > the beginning of the property chain, because the change will create a new > property there. > >> > >> Are there plans to change this? It would be nice to have something akin > to class methods (without accessing the prototype via some other, e.g. > global, reference). > >> > >> -- > >> Dr. Axel Rauschmayer > >> > >> a...@rauschma.de > >> twitter.com/rauschma > >> > >> home: rauschma.de > >> blog: 2ality.com > >> > >> > >> > >> ___ > >> es-discuss mailing list > >> es-discuss@mozilla.org > >> https://mail.mozilla.org/listinfo/es-discuss > > > > > > -- > Dr. Axel Rauschmayer > > a...@rauschma.de > twitter.com/rauschma > > home: rauschma.de > blog: 2ality.com > > > > ___ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
>> As far as I am aware, there is no way to change a property that isn’t at the >> beginning of the property chain, because the change will create a new >> property there. >> >> Are there plans to change this? It would be nice to have something akin to >> class methods (without accessing the prototype via some other, e.g. global, >> reference). > In order to access a reference to the prototype of an object, you can use > Object.getPrototypeOf. Right. That's what I didn’t think of: Iterating over the prototype chain until you get to the object that actually owns a given property and then set it there. Thanks, Axel -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
Exactly what I was looking for. Thanks. On Apr 10, 2011, at 22:18 , David Herman wrote: > function getDefiningObject(obj, key) { >if (!(key in obj)) >throw new Error("key " + key + " not found"); >while (!obj.hasOwnProperty(key)) >obj = Object.getPrototypeOf(obj); >return obj; > } > > On Apr 10, 2011, at 10:24 AM, Axel Rauschmayer wrote: > >> As far as I am aware, there is no way to change a property that isn’t at the >> beginning of the property chain, because the change will create a new >> property there. >> >> Are there plans to change this? It would be nice to have something akin to >> class methods (without accessing the prototype via some other, e.g. global, >> reference). >> >> -- >> Dr. Axel Rauschmayer >> >> a...@rauschma.de >> twitter.com/rauschma >> >> home: rauschma.de >> blog: 2ality.com >> >> >> >> ___ >> es-discuss mailing list >> es-discuss@mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss > > -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
function getDefiningObject(obj, key) { if (!(key in obj)) throw new Error("key " + key + " not found"); while (!obj.hasOwnProperty(key)) obj = Object.getPrototypeOf(obj); return obj; } On Apr 10, 2011, at 10:24 AM, Axel Rauschmayer wrote: > As far as I am aware, there is no way to change a property that isn’t at the > beginning of the property chain, because the change will create a new > property there. > > Are there plans to change this? It would be nice to have something akin to > class methods (without accessing the prototype via some other, e.g. global, > reference). > > -- > Dr. Axel Rauschmayer > > a...@rauschma.de > twitter.com/rauschma > > home: rauschma.de > blog: 2ality.com > > > > ___ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
Le 10/04/2011 19:24, Axel Rauschmayer a écrit : > As far as I am aware, there is no way to change a property that isn’t at the > beginning of the property chain, because the change will create a new > property there. > > Are there plans to change this? It would be nice to have something akin to > class methods (without accessing the prototype via some other, e.g. global, > reference). The ES5 Object.* API already provides everything you need to manipulate all properties you can find in an object (own or inherited). The "lowest-level" method to change the value of an own property is Object.defineProperty. This method can also be used to "re-configure" a property (make it non-configurable, change its enumerablity, change its "type" (data/accessor), change its writability if it is described by a data property descriptor). For examples, I recommend reading the MDN doc [1]. In order to access a reference to the prototype of an object, you can use Object.getPrototypeOf. Using both, you have enough power to achieve any change you could think of on any property of an object (own or inherited). Few platforms implement both at the moment. See [2] for reference. As Dmitry said, inherited accessor properties could be enough for what you need. David [1] https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperty [2] http://kangax.github.com/es5-compat-table/ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
On 10.04.2011 21:24, Axel Rauschmayer wrote: As far as I am aware, there is no way to change a property that isn’t at the beginning of the property chain, because the change will create a new property there. Are there plans to change this? It would be nice to have something akin to class methods (without accessing the prototype via some other, e.g. global, reference). Inherited accessor property can be change normally via assignment. Also `Object.defineProperty` is a way. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss