5

I prefer to use functional OOP style for my code (similar to the module pattern) because it helps me to avoid the "new" keyword and all problems with the scope of "this" keyword in callbacks.

But I've run into a few minor issues with it. I would like to use the following code to create a class.

namespace.myClass = function(){
  var self = {},
      somePrivateVar1;

  // initialization code that would call
  // private or public methods
  privateMethod();
  self.publicMethod(); // sorry, error here

  function privateMethod(){}

  self.publicMethod = function(){};

  return self;
}

The problem is that I can't call public methods from my initialization code, as these functions are not defined yet. The obvious solution would be to create an init method, and call it before "return self" line. But maybe you know a more elegant solution?

Also, how do you usually handle inheritance with this pattern? I use the following code, butI would like to hear your ideas and suggestions.

namespace.myClass2 = function(){
  var self = namespace.parentClass(),
      somePrivateVar1;            

  var superMethod = self.someMethod;
  self.someMethod = function(){
    // example shows how to overwrite parent methods
    superMethod();
  };

  return self;
}

Edit. For those who asked what are the reasons for choosing this style of OOP, you can look into following questions:

Community
  • 1
  • 1
  • It's generally a _bad_ idea to not use the techniques given by a language. That means you shouldn't circumvent `new`, that's just the way it's done in Javascript and it's probably the best way _in this particular language_. – Georg Schölly Jan 04 '10 at 12:39
  • Why can't you just define the methods at the top, before you try to call them? – Phil Booth Jan 04 '10 at 12:39
  • Gs, I think that using closures for creating objects with private members is a technique given by a language. Even Douglas Crockford is advocating it. I also made some performance tests before, and for small amount of objects it doesn't really matter. ( http://valums.com/b/ ) But for me it makes a code cleaner. –  Jan 04 '10 at 12:44
  • Phil, I would prefer to leave constructor at the top, as it's very common, and a lot of people are used to this way. –  Jan 04 '10 at 12:48
  • 2
    Keep in mind that you will not be able to access "private" variables in the parent class from the descendant class unless you introduce "privileged" getter and setter methods. "somePrivateVar1" in myClass2 will be a separate variable to the var of the same name in myClass1, and any changes in one won't be reflected in the other. This could cause you a lot of confusion. – Graza Jan 04 '10 at 13:15
  • 1
    Regarding the overridden methods, what are you actually trying to achieve? What you have so far looks ok, though I'd perhaps suggest adding a private namespace for the "super" methods (eg: var superMethods = {}; superMethods.someMethod = self.someMethod; self.someMethod = function(){ superMethods.someMethod(); //... }) Or are you looking for a way to automatically include a call to the superMethod in your newly overridden method? – Graza Jan 04 '10 at 13:16
  • Good tip about creating a private namespace for "super" methods. And no, I don't need to automatically include a call to the super method. I was looking for code style suggestions. –  Jan 04 '10 at 13:25
  • 1
    I'm trying to understand what's so functional about this approach. There are no higher order procedures in there and a lot of mutations actually. Not to mention the fact that the main problem is execution order because of objects mutations. – Ionuț G. Stan Jan 04 '10 at 13:31
  • Stan, I removed functional-programming tag, messed up with tags a bit. :) But I think the common name for this approach in JavaScript is functional OOP, correct me if I'm wrong. –  Jan 04 '10 at 13:37
  • @valums, I don't have a copy of Crockford's book at me, but as far as I remember he was *indeed* talking about this pattern as being functional. What can I say... it relies pretty heavily on mutating an object. It's true that using the above pattern you won't have access to a common `prototype` chain (except for `Object.prototype`) and so, some class of mutations are avoided. FP is mainly about being side-effect free, so it depends a lot on what you do in your methods. A pseudo-classical approach may be just as functional as this. IMO – Ionuț G. Stan Jan 04 '10 at 13:49
  • @valums, by the way, there are a lot of memory overheads using this method. For each object created, every function defined on that object will have to be recreated. Prototype inheritance is good. Not always (because of some of its side-effects), but it saves some memory. I can't find the link right now, but someone actually did some research about this. Anyway, I'm not implying that you should drop the pattern. I use it too, but focus on solving a problem, not on implementing a pattern. A pattern without a problem is pretty worthless and honestly I haven't seen the problem in your question. – Ionuț G. Stan Jan 04 '10 at 13:56
  • Here's some interesting read: http://www.bolinfest.com/javascript/inheritance.php – Ionuț G. Stan Jan 04 '10 at 13:58
  • @Stan Thanks, I'm aware of the memory overhead, I did some tests before using it. You can see the results here: http://valums.com/b/ I've also read an article you linked before, but honestly I don't see advantages of pseudoclassical inheritance pattern used in Closure, compared to classical prototypal inheritance. –  Jan 04 '10 at 14:13
  • @valums, nice blog post, thanks for sharing. Isn't classical prototypal inheritance the other name for pseudoclassical inheritance? Anyway, it's not that one would rule the other out. It must strike a balance, and when there's so much code just to have a handful of private variables, things get messy. – Ionuț G. Stan Jan 04 '10 at 14:24
  • @valums Sorry for writing here, can't contact you in other way, could you please take a look at this question, related to your script, http://stackoverflow.com/questions/4804304/valums-ajax-file-upload-handle-the-up-file , ajax fileuploader. Thank you! – Karem Jan 26 '11 at 15:08

4 Answers4

2

You can use Zet.js library which will help you with declaring classes in the way you want.

nemisj
  • 11,562
  • 2
  • 25
  • 23
1

Several questions occur to me, such as why you want to avoid the new operator, and why you want to call functions before they are defined. However, leaving those aside, how about something more like the following?

namespace.myClass = function(){
  var somePrivateVar1;
  var self = {};

  // initialization code that would call
  // private or public methods
  privateMethod();
  publicMethod();

  function privateMethod(){}
  function publicMethod(){}

  self.publicMethod = publicMethod;
  return self;
}
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • Thanks, one of the problem with this approach is that you don't have a reference to a current object inside your class. But in my example, it was possible to pass an object itself to another function using self variable, ex. someFunctionThatRegistersAnObject(self); –  Jan 04 '10 at 12:54
  • I tried to vote your answer, but stackoverflow shows an error "Vote too old to be changed, unless this answer is edited". Is it a bug? –  Jan 04 '10 at 13:01
  • @valums: Answer changed to address your comment. Not sure about SO error, but you should be able to change your vote now I've edited the answer. – Tim Down Jan 04 '10 at 13:09
  • Thanks, this will work too, but I think that redeclaring methods at the bottom doesn't look very clean. –  Jan 04 '10 at 13:14
  • It's not redeclaring a method as such: there's just two separate statements for declaring a function and then assigning that function as a method of `self`. I agree that the style isn't very pleasant but it's in response to your set of requirements. – Tim Down Jan 04 '10 at 13:21
0

I agree with almost every comment or answer provided so far, but to take Tim's answer one step further - he questioned why you'd want to call a method before it was defined, but offered a solution anyway, whereas I'd suggest you shouldn't call before defining (I don't know of any language where calling a method prior to defining it or at least declaring it is considered good practice), so how about:

namespace.myClass = function(){  
  //declare private vars (and self) first
  var self = {},  
      somePrivateVar1;  

  //then declare private methods
  function privateMethod(){}  

  //then public/privileged methods
  self.publicMethod = function(){};  

  // THEN (and only then) add your 
  // initialization code that would call  
  // private or public methods  
  privateMethod();  
  self.publicMethod(); // no error any more

  //then return the new object
  return self;  
} 

Is there a particular reason why this would not work for you?

Graza
  • 5,010
  • 6
  • 32
  • 37
  • Thank you, this will work ok, but I would prefer to leave the constructor at top, as it's very common, and I don't want to break habits of other programmers. –  Jan 04 '10 at 13:11
0

This is the solution I mentioned in the question. Your comments are welcome.

namespace.myClass = function(){
  var self = {},
      somePrivateVar1;

  function init(){
    privateMethod();
    self.publicMethod();
  }

  function privateMethod(){}
  self.publicMethod = function(){};

  init();
  return self;
}
  • 1
    That will work, and if you are committed to having initialisation code at the top, before declaring any of your methods, would be the only way to go, as far as I could tell. My only comment is that this is not "elegant", which is what you have asked for, however my *personal* opinion is that your criteria for how you want the method to "look" is not elegant anyway - so within this criteria, what you have there is probably the best solution. – Graza Jan 04 '10 at 13:24