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

Mark S. Miller erights at google.com
Tue Sep 9 11:11:54 PDT 2008


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.

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.

-- 
    Cheers,
    --MarkM


More information about the Es-discuss mailing list