SitePoint Sponsor

User Tag List

Results 1 to 8 of 8

Hybrid View

  1. #1
    SitePoint Enthusiast
    Join Date
    Feb 2007
    Posts
    42
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Do classes have to be global?

    I have a working JavaScript class that I want to get out of the
    global namespace. I have something like:

    Code:
      var foos;
    
      function Foo(name) {
        this.name = name;
        foos[name] = this;
      }
    
      Foo.prototype.who = function() {
        alert(this.name);
      }
    
      Bar.prototype = new Foo;
      Bar.prototype.contructor = Bar;
    
      function Bar(name,stuff) {
        Foo.call(this,name);
        this.stuff = stuff;
      }
    
      ...
    
      var aFoo = new Foo('bob');
      var aBar = new Bar('bill',{a:'x', b:'y'});
    which works fine but I want to make it myNamespace.Foo and
    myNamespace.Bar. If at the start of the previous code I add something
    like:
    Code:
    var myNamespace = new Object();
    when add myNamespace to the front of each declaration like:

    Code:
      function myNamespace.Foo(name) {
        this.name = name;
        foos[name] = this;
      }
    then try to do

    Code:
    aBar.who();
    I get an error saying that aBar() doesn't have a member who(). I've
    tried 6 different things to fix that and am beginning to think that
    objects must be at global scope. But I've spent hours Googling
    JavaScript, class, and scope and can't find anything that says that.
    On the other hand, I can't find any examples of non-global objects.

  2. #2
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Javascript doesn't actually have classes. It has objects and it has functions. Constructors are just normal functions -- It's how they are invoked, which makes them a constructor.

    Yes, you can namespace constructors, just like any other function. In Javascript, you can declare functions in two ways; Either you use the static syntax:
    Code:
    function foo() {
    }
    Or you use the dynamic syntax:
    Code:
    foo = function() {
    }
    Both accomplish the same, but the first is resolved at parse-time, while the latter is resolved at run-time. Because of this, you can't use an expression as name, with the static syntax, since the name can only be resolved at run-time. It's perfectly valid to declare a constructor using dynamic syntax though. There is no real benefit of using static syntax; It's mainly in the language to make it easier to use the language for programmers coming from C-like languages, where the dynamic syntax may seem strange.

    I recommend that you simply don't use static syntax at all. It makes your code more uniform, if you use just one syntax, and it also shows better what is really happening behind the scenes in the Javascript language.

  3. #3
    SitePoint Enthusiast
    Join Date
    Feb 2007
    Posts
    42
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    Javascript doesn't actually have classes. It has objects and it has functions. Constructors are just normal functions -- It's how they are invoked, which makes them a constructor.
    Yes, I know that; I was a little sloppy with my terminology.

    Yes, you can namespace constructors, just like any other function. In Javascript, ...
    All of which makes perfect sense except I can't get it to work!

  4. #4
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Chris.Nelson View Post
    All of which makes perfect sense except I can't get it to work!
    Code:
      var foos = {};
    
      Foo = function(name) {
        if (typeof(name) != "undefined") {
          this.name = name;
          foos[name] = this;
        }
      }
    
      Foo.prototype.who = function() {
        alert(this.name);
      }
    
      Bar = function(name, stuff) {
        Foo.call(this, name);
        this.stuff = stuff;
      }
    
      Bar.prototype = new Foo();
      Bar.prototype.contructor = Bar;
    
      var aFoo = new Foo('bob');
      var aBar = new Bar('bill',{a:'x', b:'y'});
    Note that you need to declare Bar before you can assign to its prototype property. This is because functions are regular variables in Javascript, so before you can assign to it, it needs to be declared. If you use static syntax, the chronology isn't important, since it's interpreted at parse-time.

    You had a few bugs in the code as well, which may have prevented it from working. If you aren't already, you should get firefox + firebug. If you select the tab 'Console' and enable the large command line, you can type out small program-snippets, and have them evaluated interactively. It's priceless for debugging Javascript.

  5. #5
    SitePoint Enthusiast
    Join Date
    Feb 2007
    Posts
    42
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    But I need it to work below global scope

    Thanks but my original post included re-typed code that worked in the global scope; I'm not too surprised if what I actually posted was buggy. My problem was in trying to move it down into another object. Simply prefixing ns. to all the relevant lines fails and I don't see why. Bar ends up without Foo's prototype functions.

  6. #6
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Chris.Nelson View Post
    Thanks but my original post included re-typed code that worked in the global scope; I'm not too surprised if what I actually posted was buggy. My problem was in trying to move it down into another object. Simply prefixing ns. to all the relevant lines fails and I don't see why. Bar ends up without Foo's prototype functions.
    You can't write the following:
    Code:
    function myNamespace.Foo(name) {
      this.name = name;
      foos[name] = this;
    }
    Because myNamespace.Foo is an expression, which must be evaluated. You must write it as:
    Code:
    myNamespace.Foo = function(name) {
      this.name = name;
      foos[name] = this;
    }
    Thus, your code can be rewritten as:
    Code:
      var foos;
      var ns = {}
    
      ns.Foo = function(name) {
        this.name = name;
        foos[name] = this;
      }
    
      ns.Foo.prototype.who = function() {
        alert(this.name);
      }
    
      ns.Bar = function(name,stuff) {
         ns.Foo.call(this,name);
        this.stuff = stuff;
      }
    
      ns.Bar.prototype = new ns.Foo;
      ns.Bar.prototype.contructor = ns.Bar;
    
      var aFoo = new ns.Foo('bob');
      var aBar = new ns.Bar('bill',{a:'x', b:'y'});


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •