Friday afternoon scoping quiz
Dmitry A. Soshnikov
dmitry.soshnikov at gmail.com
Fri Feb 5 15:08:40 PST 2010
Hello P,
Saturday, February 6, 2010, 1:14:33 AM, you wrote:
> ({
> 'foo': 20,
> 'test': function () {
> var f = function () {
> alert("foo:"+ foo);
> alert("this.foo:"+ this.foo);
> alert("bar:"+ bar);
> }
> with (this) {
> var foo = 42;
> var bar = 21;
> f.call(this);
> }
> }
> }).test();
When method .test is called, its this value on entering the context is
set to anonymous object. The [[Scope]] of the internal 'f' function expression
is set to current scope chain which is at the moment:
Scope chain (test): [
global,
{foo: undefined, bar: undefined}
],
where the last object - is an activation object of the execution context
of the 'test' function.
After that 'with' statement augment current scope chain with its
object which is again main anonymous object:
Scope chain (test): [
global,
{foo: undefined, bar: undefined},
{foo: 20, test: function () {...}}
]
And then, when 'f' internal function is activated, its this value is
also set to main anonymous object by the .call method. Scope chain of
the 'f' function is:
Scope chain (f): [
global,
{foo: undefined, bar: undefined},
{foo: 20, test: function () {...}},
{activation object of 'f' context}
]
And then just identifier resolution works which resolved name bindings
in the scope chain - from the deep (from the activation object) and up to the top.
That's why 'foo' identifier will be found in the second object of the
scope chain (with value 20), and 'bar' - in third.
> --
> By my reading, `foo` and `bar` are declared and initialized in
> `test`, and closed over by `f`. I expect to see:
> foo:42
> this.foo:20
> bar:21
That's possible wihtout using 'with'.
> But in Rhino, Firefox, Safari and Opera I am seeing:
> foo:undefined
> this.foo:42
> bar:21
> Flash 10 gives me the answer I expected. I have not tested other JS engines.
Incorrect behavior.
/ds
More information about the es-discuss
mailing list