By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,781 Members | 1,453 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,781 IT Pros & Developers. It's quick & easy.

Conditional include of JS files -- how?

P: n/a
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
Aug 27 '08 #1
Share this Question
Share on Google+
4 Replies


P: n/a
rocketeer wrote:
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
--
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
-- Richard Cornford, cljs, <f8*******************@news.demon.co.uk>
Aug 27 '08 #2

P: n/a
On Aug 28, 6:56*am, rocketeer <java...@sbcglobal.netwrote:
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.
--
Rob
Aug 27 '08 #3

P: n/a
rocketeer wrote:
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
Thanks,
Jerome
Aug 28 '08 #4

P: n/a
On Aug 27, 8:45*pm, dhtml <dhtmlkitc...@gmail.comwrote:
rocketeer wrote:
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.
Aug 28 '08 #5

This discussion thread is closed

Replies have been disabled for this discussion.