Conditional include of JS files -- how?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • rocketeer

    Conditional include of JS files -- how?

    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.gr oups[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(!GroupManage r) { 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
  • Thomas 'PointedEars' Lahn

    #2
    Re: Conditional include of JS files -- how?

    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(!GroupManage r) { 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, <f806at$ail$1$8 300dec7@news.de mon.co.uk>

    Comment

    • RobG

      #3
      Re: Conditional include of JS files -- how?

      On Aug 28, 6:56 am, rocketeer <java...@sbcglo bal.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.gr oups[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(!GroupManage r) {  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

      Comment

      • dhtml

        #4
        Re: Conditional include of JS files -- how?

        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.gr oups[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(!GroupManage r) { GroupManager = { groups: {} }; }
        >
        That should almost work. This:

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

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

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


        - or go directly to the global object with:-

        if(!this.GroupM anager) {
        this.GroupManag er = { 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(!GroupManage r){ // 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(!GroupManage r) would be equivalent to if(!undefined), which would
        result true.

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

        Garrett
        Thanks,
        Jerome

        Comment

        • rocketeer

          #5
          Re: Conditional include of JS files -- how?

          On Aug 27, 8:45 pm, dhtml <dhtmlkitc...@g mail.comwrote:
          rocketeer wrote:
          I've a set of Javascript classes that maintain state.  For example,
          gm.js might be:
          >
          [snip]
          var GroupManager;
          if(!GroupManage r) {
             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(!GroupManage r) 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.

          Comment

          Working...