|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. :-)
|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:
Just to be clear, when running in the Firebug console (which is how I imagined the OP was running his code), window !== this.
|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.
|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
console.log(typeof(foo) === 'undefined'); // true -- doesn't raise
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.
|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.
|Re: [JSMentors] global object property access||dhtml||2/4/11 4:48 PM|
On 2/4/11, mcot <atm...@gmail.com> wrote:As expected, getting a property off an object, the prototype chain is
searched. When that happens, if the property is not found, then
But with scope chain resolution, when the property is not resolved, an
| 11.1.2 Identifier Reference
| 10.3.1 Identifier Resolution
> console.log(foo); // this is a reference error
Identifier `foo` is resolved to a Reference with null as the base
> The Mozilla docs on Reference error simply state: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:
or even just a PrimaryExpression:
foo // a PrimaryExpression.
Identifier `foo` must be first resolved. The base object for that
| 8.7.1 GetValue (V)
| IsUnresolvableReference(V). Returns true if the base value
The MDC docs might not say it, and you didn't ask, either, but in
> I realize accessing a non existent property on an object should return
An Identifier resolution was performed on the scope chain. Just
|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.
| 11.4.3 The typeof Operator
and so `foo` is of type reference, and since the base object is
And as for the grouping operator that you used to surround foo, that
do the same thing. And ditto with
|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
That is essentially it, well, once you have that understood, ther is
But don't ever rely on that resolving because it isn't interoperable.
|Re: global object property access||mcot||2/5/11 10:41 AM|
|Re: global object property access||mcot||2/5/11 10:54 AM|
> That is essentially it, well, once you have that understood, ther isHi, well now that you mention that... I am trying to submit a proper
bug to the PyV8 project (python wrapper for V8 engine).
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).