Function.prototype.bind and [[Construct]]

Allen Wirfs-Brock Allen.Wirfs-Brock at microsoft.com
Fri Jan 16 16:54:36 PST 2009


The Kona minutes state "bind behavior: Should bind create only a call or both a call and a construct bound property? We decided to stick to last meeting's decision of creating both a call and a construct bound property. (If it were just call, then the argument for adding bind to the language at all weakens since it would do duplicate what the frameworks already do but perhaps slightly less compatibly.) "

The current ES3.1 draft does indeed support using a function created with bind (let's call that a bound function) as a constructor.  It does this by specifying that such functions have a special [[Construct]] internal property that delegates to the [[Construct]] of the original (target) function.  However, there is a problems with the current specification relating to the prototype property of the bound function.

As currently specified, the bound function has a property named "prototype" that is initialized by bind to the current value of the target functions "prototype" property.  Mark Miller says this was done to support [[HasInstance]]. However, the  value of the bound function's "prototype" property is not used by the bound function's [[Construct]] method, instead that method always delegates to the target function's [[Construct]] which uses the value of the target function's "prototype".  In addition, the value of the bound function's "prototype" property is not updated if the target function's prototype is subsequently changed nor visa versa.  As I think Brendan might say, manipulation of the bound function's "prototype" property seems like a honey point for end-user bugs.

I was originally going to talk about various specification mechanism alternatives here,  but I now think it better to just enumerate the various possible user level meaning  of bound constructors.

1) bound functions do not have a "prototype" property, cannot be used as constructors, and cannot be used with instanceOf.
2) bound functions do not have a "prototype", delegate to the target function for construction and instanceOf using the target function's "prototype" property.
3) bound functions have a "prototype" property whose value is bidirectionally shared (in the arguments object sense) with the "prototype" property of the target function.  Construction and instanceOf work using this shared prototype value.
4) (current spec.) bound functions have a "prototype" that is initialized to the value of the target function's "prototype" property.  Construction uses the target "prototype" value, instanceOf uses the bound function's "prototype" value.
5) bound functions have a "prototype" property that is initialized to the value of the target function's "prototype" property.  However, both construction and instanceOf use the target function's "prototype" value.
6) bound functions have a "prototype" property that is initialized to the value of the target function's "prototype" property. Both construction and instanceOf use the bound function's "prototype" value.
7) Initially the bound function has a "prototype" whose value appears to be unidirectionally shared with the target function and construction and instanceOf use the target function's "prototype" value.  However, if the bound function's "prototype" is explicitly set to some value, then construction and instanceOf uses the bound function's "prototype" value.   Setting the bound function's "prototype" property does not change the target function's "prototype" property.

There are subtle specification mechanics issues with almost all of the above alternatives and you may want to consider the implications with #3 (and possible #7) of having multiple bound functions that share a common target function and of having chains of bound functions. However, let's assume that any specification issues can be overcome. The more important question is which alternative has the most user utility with the least likelihood for user confusion.

My least favorite alternatives are #4 and #5. These are the honey pot alternatives.

I think that #6 and #7 have the most user utility essentially enabling a single target function to be  used as a constructor with an arbitrary number of different prototypes. However, in the specification and possibly for existing implementations it requires some sort of prototype parameterization of [[Construct]] that does not currently exist.

Finally, I have mixed feelings about #1, #2 and #3.  In particular, #3 seems too magical to easily explain to a user.

So, which alternative do you favor?  Are there any others that I missed?

Allen
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20090116/0ccb2d55/attachment-0001.html>


More information about the Es-discuss mailing list