More fun with undefined

T.J. Crowder tj at crowdersoftware.com
Fri Jun 15 09:54:16 PDT 2012


On 15 June 2012 17:00, Aymeric Vitte <vitteaymeric at gmail.com> wrote:

>  Right now I am not proposing but trying to understand why it is like this
>

Sorry, I thought you were proposing something. Your first message talked
about changing how GetValue works, apologies if I misunderstood.

Brendan could speak FAR better to "why" than I can. I would expect it's
because, as I said earlier, scope and identifier resolution is just plain
_different_ from objects and property resolution. Maybe they didn't have to
be different, but they are, and always has been. Attempts to conflate the
two (the `with` structure, for instance, which intermixes an object's
properties with scope resolution) have been unsuccessful and are now seen
to be...not the best way forward.


> ...and if by any chance a.b.c.d could be solved
>

If you want to get `a.b.c.d` but you aren't sure whether `a` is resolvable,
you can do this:

var v = typeof a === "object" &&
        typeof a.b === "object" &&
        typeof a.b.c === "object" &&
        a.b.c.d;

`v` will end up with either `undefined` or the value of `a.b.c.d`. Taking
the type of an unresolvable identifier doesn't cause a ReferenceError.


> Indeed this would require an early return from Accessors too after
> GetValue(base) . I don't understand why you focus on global var being
> created, this is not the case.
>

I wasn't trying to say your change to GetValue resulted in creating
globals. I'm just pointing out the similarity of issues between your
proposed behavior (using an implicit `undefined` when faced with getting an
unresolvable identifier) and that previous behavior (creating a global when
*putting* to an unresolvable identifier). The previous behavior was
sufficiently problematic that ES moved _away_ from doing this sort of
implicit stuff _toward_ using ReferenceError more consistently (e.g., on
put as well as get, in strict mode).


> Maybe I am misreading something in  the chain, the Accessors
> CheckObjectCoercible and GetValue IsUnresolvableReference look to be
> redundant in this case.
>
> var a;
> console.log(a.b); //TypeError for you (correct ?)- Reference error for me
> console.log(c.d);//Reference error for me
>

With the `var a;` there, my understanding is `console.log(a.b)` should
raise a TypeError, and that's what I get from V8.[1] (Be sure you have the
console open when opening that.) *Without* the `var a;` declaration, it
should raise a ReferenceError. Why:

*With* the `var a;` there, `a` is `undefined` (not unresolvable), so for
the `a.b` expression, the property accessor operation[2] gets the base
(steps 1 and 2), which will be `undefined`, and the property name (steps 3
and 4), which will be "b". Step 5 is to call CheckObjectCoercible[3]
passing in the base, which is `undefined`. CheckObjectCoercible throws a
TypeError if given `undefined`.

*Without* the `var a;`, `a` is unresolvable and so before we even get to
the property accessor, we've already run into the ReferenceError from
GetValue (which you highlighted in your original message).

Regardless of why, I for one am happy that reading from (and now in strict
mode writing to) unresolvable identifiers results in a ReferenceError. I
get nice proactive notification when I forget to declare things. :-)

[1] http://jsbin.com/ufezog
[2] http://ecma-international.org/ecma-262/5.1/#sec-11.2.1
[3] http://ecma-international.org/ecma-262/5.1/#sec-9.10

-- T.J.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20120615/84d1c7ff/attachment.html>


More information about the es-discuss mailing list