Comments: Cool Tip Of The Day: JavaScript Scope through "subscript loaders"

!(aScopeId in this.registeredScopes) also works.

(From Alex: I know. I'm a bit old-fashioned...)

Posted by Neil Rashbrook at May 8, 2005 1:22 AM

Couldn't the same be acheived by using the with statement?

(From Alex: The with statement has, to my knowledge, been deprecated. Or at the very least, is troublesome to work with. Consider that an overlay may want to load several scripts under an alternate scope...)

Posted by habacus at May 8, 2005 2:34 AM

Thinking about it, what would happen if the overlayed code adds something with an oncommand? Which scope would this be executed in?

(From Alex: I already have a solution to this -- a bit evil, but workable. I have a command event listener on the window that will modify the oncommand event listener to operate in its specified scope.)

Posted by habacus at May 9, 2005 1:48 AM

"(Omitting the second argument means it will use whatever scope it's being loaded from.)"

Not true, unfortunately. It loads to global scope by default, as far as I can see. You need to pass "this" as the second argument to load in current scope.

The tip is really cool, and it's a pity I never noticed that second parameter was /that/ useful.

--
about oncommand handlers: imho it's not a big deal to use "scopeid.handler()" there instead of just "handler()". That's what you have to do currently anyways.

and the "registry" you're proposing is an overkill imo. Making clients load in an uniquely named global object would be easier imho. |window| would play the role of |registeredScopes| then.

Posted by Nickolay Ponomarev at May 16, 2005 12:20 PM

Actually, I think this is no different from |with|. The reason |with| is deprecated, IIRC, is that it appends to the scope chain, so that when running with(obj) {a=b} you never now whether the code touches obj.a/b or the global a/b -- that is until the time comes for the with statement to be executed.

I don't think it's particularly evil to use this in our case, just it's not much better than just |with|.

"[|with|] is troublesome to work with" - I don't think so. You just wrap the whatever scripts you need to be loaded with loadSubScript in a |with| statement, it's even more flexible than mozIJSSubScriptLoader, because you can "load" stuff in different objects in the same file.

Another thing of interest is this note from the JS 1.5 reference: "Note that using a with statement will significantly slow down your code. Do not use it when performance is critical". I was wondering if this applies to our case. Simple test with |with| (source below) indicated 50% slowdown when accessing only the variables in the parent scope and 10% slowdown when only accessing vars in current scope. (~ 10 sec without |with|, 15 with |with({})| and 11 with |with({i:0,j:0}})|). I was too lazy to test with the subscript loader, if you get better results using it, please let me know.


--

var time = 0;
for(var p=0; p

Posted by Nickolay Ponomarev at May 16, 2005 1:59 PM

But of course those number assume that you only access vars. DOM manipulation is still more expensive.

Now I shut up.

Posted by Nickolay Ponomarev at May 16, 2005 3:23 PM