Conditional include of JS files -- how?

R

rocketeer

I've a set of Javascript classes that maintain state. For example,
gm.js might be:

var GroupManager { groups: {} };

Over time I add new groups to the list:

GroupManager.groups[key] = myGroup;

If I include another Javascript file that also includes a reference to
include gm.js, or do this through an Ajax call, this new loading of
gm.js overwrites my existing GroupManager variable and I lose all my
accumulated data.

So I thought I could do

if(!GroupManager) { GroupManager = { groups: {} }; }

But the GroupManager so instantiated lives only within the if()
block. And to include an initial var GroupManager simply kills state.

Are there any techniques for allowing multiple includes of a
Javascript file while detecting a previous include, allowing me to
preserve any existing variables?

Thanks,
Jerome
 
T

Thomas 'PointedEars' Lahn

rocketeer said:
I've a set of Javascript classes that maintain state.

There are probably no classes, you are likely using an implementation that
supports only prototype-based inheritance (ECMAScript 1 to 3-based). (And
no, this term does not have anything to do with the Prototype.js junk.)
If I include another Javascript file that also includes a reference to
include gm.js, or do this through an Ajax call, this new loading of
gm.js overwrites my existing GroupManager variable and I lose all my
accumulated data.

So I thought I could do

if(!GroupManager) { GroupManager = { groups: {} }; }

But the GroupManager so instantiated lives only within the if()
block.

You are mistaken. By default, ECMAScript implementations do not provide
block scoping, but lexical scoping. And since you did not declare
`GroupManager', without further information one has to assume the object
in the scope chain as which property it is accessed is the Global Object.
RTFM.
And to include an initial var GroupManager simply kills state.

Because variable instantiation comes before execution.
Are there any techniques for allowing multiple includes of a
Javascript file while detecting a previous include, allowing me to
preserve any existing variables?

The only possibility I know to work around that is

if (typeof x == "undefined")
{
eval('var x = "foo";');
}


PointedEars
 
R

RobG

I've a set of Javascript classes that maintain state.  For example,
gm.js might be:

var GroupManager { groups: {} };

Over time I add new groups to the list:

GroupManager.groups[key] = myGroup;

One approach is to put a declaration at the start of the file in the
appropriate scope (global here) and conditionally assign it a value:

var groupManager = groupManager || {groups: {}};


So groupManager is a global variable referencing an object that holds
whatever (provided you are aware that any time groupManager evaluates
to a falsey value it will be assigned a reference to the object
literal on the right hand side of the || expression).

Declaring a variable with var can't alter the value of an existing
variable.

Oh, by convention only constructors or constants start with a capital
letter, hence groupManager (or GROUPMANAGER for constants, but I don't
use that). :)

If I include another Javascript file that also includes a reference to
include gm.js, or do this through an Ajax call, this new loading of
gm.js overwrites my existing GroupManager variable and I lose all my
accumulated data.

So I thought I could do

if(!GroupManager) {  GroupManager = { groups: {} }; }

If GroupManager has not be declared or initialised some other way,
that is a syntax error. If you include var to declare GroupManager,
it is essentially the same as the suggestion above does, i.e.

if (!groupManager) { var groupManager = { groups: {} }; }

is essentially the same as:

var groupManager = groupManager || {groups: {}};

But the GroupManager so instantiated lives only within the if()
block.

That is an incorrect conclusion, there is no block scope in
javascript.

 And to include an initial var GroupManager simply kills state.

Only if you unconditionally assign a value, the declaration by itself
never changes the value per ECMA-262.

Are there any techniques for allowing multiple includes of a
Javascript file while detecting a previous include, allowing me to
preserve any existing variables?

I don't think detecting script file includes is a suitable strategy,
you want to detect whether the variable already has a value and if so,
leave it alone and if not, initialise it.

A declaration with conditional assignment does just that.
 
D

dhtml

rocketeer said:
I've a set of Javascript classes that maintain state. For example,
gm.js might be:

var GroupManager { groups: {} };

Over time I add new groups to the list:

GroupManager.groups[key] = myGroup;

If I include another Javascript file that also includes a reference to
include gm.js, or do this through an Ajax call, this new loading of
gm.js overwrites my existing GroupManager variable and I lose all my
accumulated data.

So I thought I could do

if(!GroupManager) { GroupManager = { groups: {} }; }

That should almost work. This:

if(!GroupManager) {
var GroupManager = { groups: {} };
}

will do the trick. What RobG posted will work, too. So will:-

var GroupManager;
if(!GroupManager) {
GroupManager = { };
}


- or go directly to the global object with:-

if(!this.GroupManager) {
this.GroupManager = { groups:{} };
}

All work.
But the GroupManager so instantiated lives only within the if()
block. And to include an initial var GroupManager simply kills state.
By now you know that is not true. The relevant spec is Ecma-262 r3,
section 10.1.3.

The variable declarations are taken first, before statements so the
effect would be:

var GroupManager; // in first pass.

if(!GroupManager){ // in second pass.
GroupManager = { groups: {} };
}
Are there any techniques for allowing multiple includes of a
Javascript file while detecting a previous include, allowing me to
preserve any existing variables?

You could safely use the first one I tweaked. Why? Well, because what
happens when a variable statement is encountered is that if there is
already property of the variable object with that same name, then it's
value is not changed, however if there is not already a variable of that
same name, it's value is undefined.

So, if GroupManager was already defined, then the variable declaration -
var GroupManager; - wouldn't change its value.

But if GroupManager was not already defined, then the variable
GroupManager would have value undefined, and the statement
if(!GroupManager) would be equivalent to if(!undefined), which would
result true.

You're good to go, and you don't need eval.

Garrett
 
R

rocketeer

rocketeer said:
I've a set of Javascript classes that maintain state.  For example,
gm.js might be:
[snip]

var GroupManager;
if(!GroupManager) {
   GroupManager = { };

}
[snip]

So, if GroupManager was already defined, then the variable declaration -
var GroupManager; - wouldn't change its value.

But if GroupManager was not already defined, then the variable
GroupManager would have value undefined, and the statement
if(!GroupManager) would be equivalent to if(!undefined), which would
result true.

You're good to go, and you don't need eval.

Garrett

[snip]

Thanks for the advice (Mr. PointedEars (above) is a bummer...). I
don't have any problems with the MSIE browser. But I have to support
FireFox, too. When I do this:

var GroupManager = GroupManager || { groups: {} };

or the if(...) version, FireFox 3 (I no longer have version 2 around
anywhere) goes off to odd places (wyciwyg://1/http://and_so_on). Why
and where it goes isn't as important as I don't get the desired
behavior. So unless there is another tweak here I'll have to live
with my initial situation.

I think I will look at the EMCAScript specification. I figured that
var worked like (name your favorite language) and cleared an existing
variable having that name. So I'll slowly learn ...

Jerome.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top