Improving ECMAScript as a compilation target
Allen.Wirfs-Brock at microsoft.com
Mon May 4 22:46:02 PDT 2009
>From: Brendan Eich [mailto:brendan at mozilla.com]
>On May 4, 2009, at 6:20 PM, Allen Wirfs-Brock wrote:
>> In the function defined for the example's invoke item the first
>> argument to apply probably should be obj rather than peer.
>Possibly, but in the example peer[id] may be a function that insists
>on |this| being bound to peer, not obj. If the function is pure, the
>arguments flow in and a result comes back, and the catchall delegates
>without mutating peer or obj. If the function mutates |this|, then the
>effects can be recovered by calling other methods, or by property
>access, which again is delegated without a wrapper.
You're right it is probably situational. As I look at the example again, I'm uncertain about your intent for the invoke and construct properties of the catch all descriptor. My original assumption was that they would be invoked if obj (the object itself, not one of its properties) was invoked or new'ed. However, in that case there wouldn't be a property id to pass as an argument to the handler function, yet the function signatures for invoke and construct in the example have an id argument.
The other possibility, at least for invoke, is that the handler is invoked whenever an attempt is made to call the value of an non-existent property of obj. In other words invoke and get are mutually exclusive. I'm guessing that wasn't you intent as it really doesn't match the ES meta-model. However, I think I was momentarily thinking that way when I made the observation about passing obj rather than peer. That raises for me some usability concerns. I'm well aware that a "method" is called by first getting the property value and then invoking the function value returned from the get but I still made the mental slip of thinking that invoke in the catch all descriptor was about calling a method of obj rather than calling obj itself. I expect that the typical non-expert JavaSript programmer will be even more prone to making that mistake.
>> I would be inclined to specify an additional argument (probably the
>> first) for each handler function that would be passed the "this"
>> value. Closure capture like is done in the example works but my
>> intuition is that there will be situations where it would be handy
>> to use the same catch-all descriptor for several objects.
>Agreed, but why not use |this| instead of an extra (leading) parameter?
Good point, it depend upon whether the model is that the entire descriptor is associated with obj as its catch all handler or whether the individual handler functions are separately associated with obj. If the entire catch all descriptor object is associated with obj then I would expect that when one of its methods is invoked that the this object would be the descriptor object rather than obj. On the other hand, if the descriptor object is just a way to aggregate a bunch of optional arguments to defineCatchAll (similar to the defineProperty pattern) then it is reasonable to assume that the individual handler functions are invoked as if they were methods of obj and thus the this value would be obj.
More information about the es-discuss