global object property access

Showing 1-14 of 14 messages
global object property access mcot 2/4/11 3:44 PM
I am currently seeing some weird behavior with the global object:

console.log(window.foo);   // this returns undefined
console.log(this.foo);        // this returns undefined
console.log(foo);              // this is a reference error

The Mozilla docs on Reference error simply state:

A ReferenceError is thrown when trying to dereference a variable that
has not been declared.

I realize accessing a non existent property on an object should return
undefined... which accounts for the first two cases... but whats going
on in the third case?
Re: [JSMentors] global object property access Michael Geary 2/4/11 4:07 PM
There's nothing weird going on there, it's all defined and expected behavior.

The first two cases are identical to each other, because window === this when your code runs in the global scope. And as you noted, it is not an error to attempt to dereference a nonexistent property of an object - you simply get the undefined value.

The third case is not the same thing. The name 'foo' has not been defined to be anything at all, so it's an error to use it all by itself like that.

As far as why it works the way it does, it's just because that's the way it works, and how the standard is written. :-)

-Mike


--
To view archived discussions from the original JSMentors Mailman list: http://www.mail-archive.com/jsmentors@jsmentors.com/

To search via a non-Google archive, visit here: http://www.mail-archive.com/jsmentors@googlegroups.com/

To unsubscribe from this group, send email to
jsmentors+...@googlegroups.com

Re: [JSMentors] global object property access Jason Persampieri 2/4/11 4:16 PM
On Fri, Feb 4, 2011 at 4:07 PM, Michael Geary <m...@mg.to> wrote:
The first two cases are identical to each other, because window === this when your code runs in the global scope. And as you noted, it is not an error to attempt to dereference a nonexistent property of an object - you simply get the undefined value.


Just to be clear, when running in the Firebug console (which is how I imagined the OP was running his code), window !== this.

_jason 
Re: global object property access Angus Croll 2/4/11 6:53 PM
Re: [JSMentors] global object property access kangax 2/4/11 7:04 PM


In the third case, you're trying to resolve a so-called undeclared identifier. 

When `console.log(foo)` is evaluated, first, `foo` identifier needs to be resolved against the current scope chain. Once it's resolved, its value can then be passed to `console.log`. When resolving `foo`, ES3-based implementations follow behavior described in 10.1.4 — Scope Chain and Identifier Resolution. If you look at 10.1.4, you'll see that during this resolution, all objects in the scope chain are being searched for a property corresponding to an identifier in question — "foo" in this case. Since the only object in the current scope chain are the global object (considering that you're executing that statement from within the global code), the Global Object is the only object that's being searched for "foo". "foo" doesn't exist there of course, and there are no more objects in the scope chain, which brings us — via step 1 ("Get the next object in the scope chain. If there isn't one, go to step 5") — to step 5. Based on that step, `foo` is supposed to return a reference with base object `null` and property name "foo". We're almost there. The returned reference now goes through internal `GetValue` method (during that `console.log(...)` function call), which is defined to throw a ReferenceError when passed an object with `null` base. So there you have it — why resolving `foo` (or rather — `console.log(foo)`) throws ReferenceError.

[...]

-- 
kangax
Re: global object property access mcot 2/4/11 7:54 PM
Hi.  I am still reading up on this but here are some more tests I have
run:

console.log(typeof(foo) === 'undefined');         // true  -- doesn't raise
reference error.
foo;                                                                 // reference error even without the call to console.log
Re: global object property access mcot 2/4/11 7:57 PM
By the way I am running these tests in the spidermonkey shell and in
chrome using the dev tools.  I substitute console.log for print() in
the spidermonkey shell.
Re: [JSMentors] Re: global object property access Michael Geary 2/4/11 10:09 PM
Yes, that's correct. The typeof operator does not require its operand to be defined. When its operand is not defined, typeof returns the string 'undefined'. All correct, expected behavior.


--
To view archived discussions from the original JSMentors Mailman list: http://www.mail-archive.com/jsmentors@jsmentors.com/

To search via a non-Google archive, visit here: http://www.mail-archive.com/jsmentors@googlegroups.com/

To unsubscribe from this group, send email to
jsmentors+...@googlegroups.com

Re: [JSMentors] Re: global object property access kangax 2/4/11 10:23 PM


That's because `typeof` operator never calls `GetValue` on its operand (`GetValue` is what throws ReferenceError, as explained earlier). This was done specifically so that `typeof` can be applied to undeclared identifiers (and return "undefined" rather than throw an exception). `foo` in second statement, however, does get passed through `GetValue` — as any other ExpressionStatement; hence ReferenceError.

[...]

-- 
kangax
Re: [JSMentors] global object property access dhtml 2/4/11 4:48 PM
On 2/4/11, mcot <atm...@gmail.com> wrote:
> I am currently seeing some weird behavior with the global object:
>
> console.log(window.foo);   // this returns undefined
> console.log(this.foo);        // this returns undefined
As expected, getting a property off an object, the prototype chain is
searched. When that happens, if the property is not found, then
`undefined` results.

But with scope chain resolution, when the property is not resolved, an
error results.

| 11.1.2   Identifier Reference
| An Identifier is evaluated by performing Identifier Resolution
| as specified in 10.3.1. The result of evaluating an Identifier
| is always a value of type Reference.

...

| 10.3.1   Identifier Resolution
| Identifier resolution is the process of determining the binding of an
| Identifier using the LexicalEnvironment of the running execution context.

> console.log(foo);              // this is a reference error
>

Identifier `foo` is resolved to a Reference with null as the base
object. In ES5, it looks as if it is a Reference with base object as
`undefined`. With either spec, the result will be the same
ReferenceError. ES5 gets a little fancy with the explanation.

> The Mozilla docs on Reference error simply state:
>
> A ReferenceError is thrown when trying to dereference a variable that
> has not been declared.
>
They mean that when you try and get the value of an Identifier in a
PrimaryExpression and the Identifier is not resolved, then the base
object is null (or now `undefined`) that the attempt to get at the
value is going to result in a ReferenceError.

So when you have an Expression like:

console.log(foo);

or even just a PrimaryExpression:

foo // a PrimaryExpression.

Identifier `foo` must be first resolved. The base object for that
value is null (or so"undefined") and the when the expression is
evaluated, it tries to get the value, and then finds the base object
is null and throws a ReferenceError is thrown.

| 8.7.1   GetValue (V)
|
|   1. If Type(V) is not Reference, return V.
|   2. Let base be the result of calling GetBase(V).
|   3. If IsUnresolvableReference(V), throw a ReferenceError exception.

...

| IsUnresolvableReference(V). Returns true if the base value
| is undefined and false otherwise.

The MDC docs might not say it, and you didn't ask, either, but in
strict code, assignment to undeclared Identifier will result in
referenceerror too.

> I realize accessing a non existent property on an object should return
> undefined... which accounts for the first two cases... but whats going
> on in the third case?

An Identifier resolution was performed on the scope chain. Just
remember the difference when getting a property fails: With object
properties - the prototype chain is used and the result is undefined.
With unqualified Identifiers, the scope chain is searched in the
result is ReferenceError.
--
Garrett

Re: [JSMentors] Re: global object property access dhtml 2/4/11 8:27 PM
On 2/4/11, mcot <atm...@gmail.com> wrote:

Well you're leading me right through the spec.
http://ecma262-5.com/ELS5_HTML.htm#Section_11.4.3

| 11.4.3   The typeof Operator
| The production UnaryExpression : typeof UnaryExpression is
| evaluated as follows:
|
|
| # Let val be the result of evaluating UnaryExpression.
| # If Type(val) is Reference, then
|
|   1. If IsUnresolvableReference(val) is true, return "undefined".

and so `foo` is of type reference, and since the base object is
undefined, IsUnresolvableReference results true, and the result is
undefiend.

And as for the grouping operator that you used to surround foo, that
doesn't apply GetValue either.

typeof foo;
typeof(foo);

do the same thing. And ditto with
delete foo;
delete(foo);
That's what it says in "11.1.6   The Grouping Operator"
http://ecma262-5.com/ELS5_HTML.htm#Section_11.1.6
And it works the same way in EcmaScript Ed 3.
--
Garrett

Re: [JSMentors] Re: global object property access dhtml 2/4/11 11:08 PM
Yes, that's exactly right. `foo` on its own is an Identifier, which is
a PrimaryExpression as explained earlier.

Real simple though, if you have PrimaryExpression Identifier, it is
resolved up scope chain. If you have property access (using iether `.`
or `[""]` then it is resolved up the prototype chain).

That is essentially it, well, once you have that understood, ther is
also the [[GlobalScopePolluter]] to confuse you. It's a bad featre and
I only mention it for completeness. GlobalScopePolluter is an extra
object above the global object that browsers provide so to resolve
elements by there id and name.

<div id=foo>dd</div>
<script type="text/javascript">
  alert( foo ); // [object HTMLDivElement]
</script>

But don't ever rely on that resolving because it isn't interoperable.
--
Garrett

Re: global object property access mcot 2/5/11 10:41 AM
Hi.  Thanks to everyone for the help.  I think I understand it now and
the specs make more sense after seing your explanations.



On Feb 5, 2:08 am, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> On 2/4/11, Juriy Zaytsev <kan...@gmail.com> wrote:
>
>
>
>
>
>
>
Re: global object property access mcot 2/5/11 10:54 AM


On Feb 5, 2:08 am, Garrett Smith <dhtmlkitc...@gmail.com> wrote:

> That is essentially it, well, once you have that understood, ther is
> also the [[GlobalScopePolluter]] to confuse you. It's a bad featre and
> I only mention it for completeness. GlobalScopePolluter is an extra
> object above the global object that browsers provide so to resolve
> elements by there id and name.
>
> <div id=foo>dd</div>
> <script type="text/javascript">
>   alert( foo ); // [object HTMLDivElement]
> </script>
>
> But don't ever rely on that resolving because it isn't interoperable.
> --
> Garrett

Hi, well now that you mention that... I am trying to submit a proper
bug to the PyV8 project (python wrapper for V8 engine).

http://code.google.com/p/pyv8/issues/detail?id=71

Using PyV8 a python object can become the global object.  In python
you can use a __getattr__ method on an object that is the default that
gets called when an object does not have a particular property or
method defined for a name.  It seems like this would be very tricky to
map into that setting because "foo" and "<global object>.foo" my both
try to resolve against the global object and end up calling
__getattr__ if you have it defined.  In that case I guess the Python
programmer would have to decide wether or not to return undefined or
somehow trigger a reference error (currently raising a js error from
Python is not one of the features of PyV8).