Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Comparable questions have surely been asked before but I'd like to hear some words about my specific way of implementing Javascript classes.

Let me first start with a Javascript example taken from a real-life application I've been working on recently.

Example

PageControl= new function() {
  var self= this;

  // example additional control bound to page control
  var grid= new GridControl();

  self.initialise= function() {
    // initialise form fields, controls etc.
  };

  // example function
  self.load= function(id) {
    // reloads form with new data
  };

  $(document).ready(function() {
    self.initialise();
  });
};

Each page has its own PageControl instance with specific tasks solely relevant for the given page.

Question:

I'm not looking for alternative ways of how to implement it, I'd just want to know if the above example is bad or wrong code. The above structure has worked great so far, even if I work with sub controls like PageControl.grid.reload(); but I don't want to stick to error-prone code.

share|improve this question

migrated from stackoverflow.com Jun 28 at 16:00

This question came from our site for professional and enthusiast programmers.

2  
Hmm... Perhaps this question would be better suited to the Code Review site. –  Lix Jun 28 at 11:05
    
self.initialise(); should likely be PageControl.initialise(); in the onload –  mplungjan Jun 28 at 11:07
    
@mplungjan I guess you are right, oddly it does work with self.initialise();. Perhaps that's because it is executed in the context of PageControl? –  SaschaM78 Jun 28 at 11:31
1  
Self works because it's the same as PageControl to learn more about constructor functions, the value of this and prototype you can read this answer: stackoverflow.com/questions/16063394/… –  HMR Jun 28 at 13:42
    
@mplungjan No, PageControl.initialise() is going to call the wrong function for PageControl instances made later, if the class function was reusable. self.initialise() (defined at the top of the constructor function) is correct and is going to be the current instance in every case. –  Izkata Jun 28 at 17:38

2 Answers 2

up vote 2 down vote accepted

I'm not sure if it's bad or wrong, but it is confusing.

Your PageControl is not a class, it's an instance of an anonymous class. In javascript a class is a function object intended to be used with the new keyword to create instances of that class.

Your code uses the new keyword on an anonymous function.

What you're trying to accomplish, I think, is usually done using the IIFE (Immediately-invoked function expression) pattern.

PageControl= (function() {
  // you can create private variables and functions for use between your
  // functions, or add them to the self object to make them available.

  // example additional control bound to page control
  var grid= new GridControl();

  // Create your singleton w/ its member functions and possibly other properties
  // these functions can use 'this' to reference other members of the self object.
  // do it here so it can be referenced in the function closure used by
  // $(document).ready
  var self = {
    initialise: function() {
      // initialise form fields, controls etc.
    },

    load: function(id) {
      // reloads form with new data
    },

    // example additional control bound to page control
    grid: grid
  };

  $(document).ready(function() {
    self.initialise();
  });

  return self;      
})();

// your page can call those methods on the PageControl
PageControl.load("myId");
PageControl.grid.reload();

The key to the IIFE pattern is that you define a function expression that returns an object and then immediately call (execute) that function (function() {})();.

share|improve this answer
    
The IIFE pattern is itself confusing. :-). I prefer OPs, or, even better IMHO, using Foo.prototype.functionName = function(){} etc... –  user949300 Jun 28 at 22:06
    
I would rather create a real class, and use Foo.prototype.methodName for the methods myself, but IIFE is a very common js pattern that is how I think most js programmers today would do what @SaschaM78 describes. –  Mike Lippert Jun 29 at 1:59
    
Thanks for the followup. I'm fairly new to JavaScript and learning some of the strange idioms. –  user949300 Jun 29 at 23:34
1  
I personally don't like the prototype way because methods and attributes are defined outside of the class/object instead of being wrapped inside the class' body. Perhaps I should simply accept the fact that it's very common and a defacto standard. –  SaschaM78 Jun 30 at 12:37
    
@SaschaM78 I don't like it either, but more because AFAIK you have to access everything with foo.variable, while defining the methods inside the main function creates closures allowing for private variables and no prefix necessary –  Izkata Jul 1 at 0:38

There is no "right way" to write objects in javascript. There are multiple different techniques each with pros and cons, or just different flavors.

I personally like the style that you have declare "public" functions in your example because by my experience it helps lowering the learning curve for people with OOP background.

But it penalizes because you are re-creating every function on each instantiation and that as a cost. It also makes your objects unstubbable through tools like Sinon.js, because there isn't a prototype for it to mess with.

share|improve this answer
2  
I flagged my question to be moved to the Code Review forum. Thanks for your comment, in the way I use it there is no second instance of the same class, it's more like a Singleton-approach to have exactly one instance for one page. –  SaschaM78 Jun 28 at 11:36

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.