0

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.

migrated from stackoverflow.com Jun 28 '14 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 '14 at 11:05
  • self.initialise(); should likely be PageControl.initialise(); in the onload – mplungjan Jun 28 '14 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 '14 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 '14 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 '14 at 17:38
2

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() {})();.

  • The IIFE pattern is itself confusing. :-). I prefer OPs, or, even better IMHO, using Foo.prototype.functionName = function(){} etc... – user949300 Jun 28 '14 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 '14 at 1:59
  • Thanks for the followup. I'm fairly new to JavaScript and learning some of the strange idioms. – user949300 Jun 29 '14 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 '14 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 '14 at 0:38
0

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.

  • 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 '14 at 11:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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