[Greasemonkey] Javascript lexical scoping question

Julien Couvreur julien.couvreur at gmail.com
Thu Apr 14 23:35:56 EDT 2005


>From what I read, "window" is used as the global environment in
Netscape browsers. It's basically the root of all lexical scopes.

Jeremy, I was digging in the ECMAScript spec, but I totally agree it is opaque.
I've been reading this page on javascript closures, which is a bit
easier to read: http://jibbering.com/faq/faq_notes/closures.html

This article also helped me understand a bit more about prototype:
http://www.webreference.com/js/column79/index.html


Sorry for making this a long and possibly boring email again, I've
been looking into javascript and closures for a good part of the day.
Here's a couple things that I don't quite get yet. 

1) It looks like everything is an object, including 
function foo() { print('hello'); }, which is really the same as new
var foo = Function("print('hello');"). Yet if you call it with "new"
it becomes the constructor for an object.

2) I understand how lexical scopes work (something like a linked-list
of hashtables), but I don't get where "this.x" member variables get
stored. What does "new" do to make "this" work?

3) When does such a Function object capture the lexical environment,
thus becoming a closure? When a closure is invoked, how does it look
up variables? Is it looking down the lexical environment captured by
the closure? Is it looking down the lexical environment in which the
closure in invoked?

4) I made some experiment to help me clarify my understanding:
In this first one, it looks like the "show" function picks up x from
the scope in which it gets called (since it isn't defined in the scope
on which it was closed):
 > var ctor = function() { this.show = function() { print(x); } }
 > var obj = new ctor();
 > obj.show();
 ReferenceError?: x is not defined
 > var x = 1;
 > obj.show();
 1

But in this second one, "show" doesn't pick up the value of x. How come?
 > var ctor = function() { this.show = function() { print(x); } }
 > var obj = new ctor();
 > obj.show();
 ReferenceError?: x is not defined
 > var foo = function() { var x = 2; obj.show(); }
 > foo();
 ReferenceError?: x is not defined

5) I just understood something about prototypes, that I'd like to share:
Even though two objects (obj1 and obj2) share the same object instance
(new objectBaseCtor()) as their prototype, they don't actually share
any state that way.
 
When a member variable is looked up, it gets looked up the chain of
prototypes. But when a member variable is set, the prototype chain
isn't involved and the member variable is directly set on the object
instance that is modified (obj1 in this case)

 > function objectCtor() { this.visible = 5; }
 > function objectBaseCtor() { this.shared = 20; this.change =
function(value) { this.shared = value; } }
 > objectCtor.prototype = new objectBaseCtor();
 [object Object]
 > var obj1 = new objectCtor();
 > var obj2 = new objectCtor();
 > obj1.shared;
 20
 > obj2.shared;
 20
 > obj1.change(10); // this really adds a new member to obj1, called
"shared" with value 10
 > obj1.shared;
 10
 > obj2.shared; // but obj2 still doesn't have that member, so the
lookup for it goes to its prototype object
 20



Douglas Crockford has many great articles on javascript including one
named "JavaScript: The Wrrrld's Most Misunderstood Programming
Language". I read it a couple of years back and though I got it. But
looking at it again, I still feel like there is so much to learn ;-)
http://www.crockford.com/javascript/

Cheers,
Julien


More information about the Greasemonkey mailing list