Coercing 'this' (was: Topic list - pending changes and issues for the ES3.1 spec)

Sam Ruby rubys at intertwingly.net
Wed Sep 10 03:07:31 PDT 2008


On Tue, Sep 9, 2008 at 2:11 PM, Mark S. Miller <erights at google.com> wrote:
> On Tue, Sep 9, 2008 at 9:21 AM, Mark S. Miller <erights at google.com> wrote:
>> What should be the rules for coercing non-object 'this' values?
>
> In a previous thread we've already settled that ES3.1-strict will not
> coerce null or undefined 'this' values. In order to do this, we're
> going to migrate the spec language for coercing a null-or-undefined
> 'this' from the caller-side that scattered all over the spec (where
> it's hard to make it conditional on strictness), to the callee side in
> section 11.1.1. For non-strict code, this should make no observable
> difference.
>
> Some open questions:
>
> The ES3 spec language uses null as the implicit 'this' value
> associated with calling a function as a function. However, since the
> current spec language also coerces both null and undefined to the
> global object, it is unobservable whether null or undefined is used as
> the implicit 'this' value. In ES3.1 strict this difference becomes
> observable. In the interests of explaining 'this'-binding as being
> more like parameter-binding, I would like to see this changed to
> undefined. Calling a function as a function is like calling it without
> an argument for its 'this' parameter. I think this is more intuitive.
>
> When a primitive non-object type (number, boolean, string, presumably
> decimal) is passed as a 'this' value, the ES3 spec coerces it to a new
> corresponding wrapper object each time. This fresh allocation is
> observable and therefore expensive. For example, let's say someone
> adds a new method to String.prototype:
>
>> String.prototype.capture = function() { return this; };
>> var foo = "foo";
>> foo.capture() === foo.capture()
>   false
>
> The expense of this allocation imposes a cost on all programs in order
> to provide a semantics that's strictly worse than not providing it,
> and which hardly any programs will ever care about anyway. To avoid
> the extra expense within the current semantics, an implementation
> would have to do escape analysis. IIRC, the ES4 spec avoids requiring
> this allocation, as that was felt to be an incompatibility everyone
> could live with. I agree. I propose that primitive 'this' values not
> be coerced at all.

Let's posit for the sake of discussion that a primitive decimal type
is in and we proceed as you describe above.  Furthermore, and just for
the sake of simplicity as it isn't really pivotal, let's assume that
all named Decimal methods are "static", so there is no instance
methods of interest.

In such a scenario, is there value in providing a Decimal wrapper type
at all?  Could new Decimal('5') simply throw an exception and a
footnote be placed someplace in the spec that ECMA TC39 reserves the
right to change this behavior in future revs of the spec?

I'm not asking because I consider a Decimal wrapper is hard to
implement, but because I don't understand what value such a wrapper
would provide other than to be available for the situation you
describe above.

> If primitive 'this' values are no longer coerced, we can still explain
> the semantics of property lookup of an expression like 'foo.capture()'
> by saying that the property is looked up in the wrapper's prototype.
> Or we could say that the property is looked up after wrapping, but a
> method call proceeds with the original unwrapped value. In other words
>
>    "foo".capture()
>
> should be equivalent to
>
>    Object("foo").capture.call("foo")
>
> given the original bindings for Object and Function.call.

It occurs to me that the latter case (looking up after wrapping)
trades a single wrapping at function entry against potentially
multiple wrappings that may occur inside the function.

> --
>    Cheers,
>    --MarkM

- Sam Ruby


More information about the Es-discuss mailing list