11

At our company we have pretty large body of PrototypeJS based JavaScript code, which we are porting to jQuery for several reasons (not really important here). I'm trying to set up coding guidelines to make/keep things tidy during the porting.

One observation from wading through the prototype based implementation is that a lot of code is written in OOP style (using Prototype's Class.create), but the code is not "object oriented" in spirit. The general pattern I've seen: one "constructor" which you are expected to call (but not call twice, because the constructor uses hardcoded DOM id's), a bunch of other "functions" and event handlers, which you are not expected to call (but the because there is no "private" in JavaScript, you don't know that) and data sharing between all these functions through this. Seen from the caller's point of view there is just one "callable" and nothing else.

I'm starting to believe that OOP in JavaScript can and maybe should be avoided in a lot of cases. At least for our use case, which is not the next generation Goole Wave UI, but simply put: a bit of AJAX based enhancements, registering some event handlers here and there, minor DOM manipulations and such.

  • the functionality we need seems to be implementable just fine in the typical jQuery non-OOP way, using closure magic to obtain encapsulation and privateness. As side effect, the minification efficiency of the ported code is much better.
  • OOP in JavaScript is non-traditional and confusing if you are coming from a "traditional" background. There are a lot of attempts and frameworks to approximate traditional OOP, but IMHO this makes things even more confusing and fragile.
  • One thing that Crockford's "JavaScript the good parts" taught me, is that the true power of Javascript lies in function scopes and closures, much less in OOP patterns.

I'm wondering if there is wider support for this feeling that OOP in JavaScript doesn't really cut it as the sacred mantra, like it is in other languages/platforms. And, in extension, what kind of non-OOP/closure based patterns are much more preferable.

11
  • 3
    Javascript does its "OOP" using functions and closures. Private methods are realized by declaring them the right way in the right scope. Yes, it's different, but it's possible. It doesn't have to be "sorta OOP", you just need to apply it correctly. In fact, it helps to wrap your head around Javascript's way of OOP, since it gives you a new perspective on what "classic OOP" in other languages is and how little you actually need to implement it; one language construct (function) is sufficient.
    – deceze
    CommentedMay 15, 2013 at 15:59
  • 1
    @deceze That would make a decent answer, if you added a short code sample.CommentedMay 15, 2013 at 16:06
  • @gnat: The first one, maybe. Not the second. I think the OP is asking the opposite.CommentedMay 15, 2013 at 16:09
  • 1
    @Stefaan "Classes" are containers that data is injected into which is only accessible to certain functions ("methods") within that container. This can be modeled perfectly using functions and aspects of closures, it's the same idea. Maybe you're thinking of deeply nested trees of callbacks within callback; if so nobody said that's either good or OOP.
    – deceze
    CommentedMay 15, 2013 at 16:16

3 Answers 3

4

People tend to get caught up in advanced patterns with OOP. MVC, MVVM, MVVC and every other permutation of 'M', 'V', and 'C'. I've never opened up a js project with 20,000+ lines and said to myself: "Thank god this is in MVC", because the reality is that most projects with 20,000+ lines are going to be a terrible mess.

Having said that, I still think large projects are almost impossible without OOP. At the very least, the ability to write complex objects and store them in separate files and namespace-protect them from collisions using a library like dojo will save you thousands of hours of painful debugging.

"Oh", you might say to yourself, "Well, I can write modular groups of functions in separate javascript files with the best of them. I don't need to use OOP." Well, my friend- congratulations, because you're already effectively using OOP without even knowing it. So as long as that's the case, why not just go one step further and use actual classes?

It's true that javascript relies on the prototype model, however, the base of OOP is pretty much inheritance/encapsulation/polymorphism, and javascript can do that perfectly well. Take a look at dojo.js.

20
  • 2
    Is code written in a browser really large enough to warrant full-scale object-orientation?CommentedMay 15, 2013 at 16:11
  • 3
    @RobertHarvey: Allan Kay argued that by role browser are operating systems rather than applications (as opposed to how they were designed in the end). In that spirit I would ask whether code written "in an OS" is really large enough to warrant full-scale object-orientation. It's no longer uncommon for JavaScript project to have 1MLOC and more.
    – back2dos
    CommentedMay 15, 2013 at 16:16
  • 2
    @back2dos: No disrespect to Alan Kay, but that comment makes no sense. Browsers are not operating systems, and they never will be (they don't have first-class access to the file system, for starters). I might call a browser an application platform, but not an operating system.CommentedMay 15, 2013 at 16:21
  • 2
    "why not just go one step further and use actual classes?" - Because many modules (while being objects) neither use constructors nor inheritance. And even if you need only one of them there's no need for a full-blown class-emulation.
    – Bergi
    CommentedMay 15, 2013 at 16:31
  • 3
    @RobertHarvey: No disrespect to you, but that comment makes no sense. Firstly, an operating system is hardly defined by "first-class access to the file system". By that definition, iOS is hardly an OS. And there have been operations systems, before there have been file systems. Also you can buil a web app against a web service through HTTP that will give you anything an FS gives you.
    – back2dos
    CommentedMay 15, 2013 at 16:31
2

I feel it's important to point out a couple of things:

  1. OOP and classes are two fully orthogonal concepts. Classes could just as well work with structs/records (and in fact they do in some languages). They incidentally happen to be useful for constructing specific kinds of objects.
  2. Access control is a nice tool for encapsulation, but it's not a prerequisite. In JavaScript it's common to prefix "private" members of an object with an underscore. Whether or not you choose to access those anyhow is for you to decide. In most languages there are some means to get past access control if you really want to. It's just a really silly thing in general to write code against something that was never consciously exposed by a human being for you to consume (and can for example change at any time).
  3. OOP is certainly not about how specific parts of your system are implemented (let alone the syntax involved) and I would thus argue that the implementation cannot be "object oriented in spirit" or not. OOP is mostly a relatively clever mechanism for indirection built on encapsulation and polymorphism. In essence, it is little more than "Tell, Don't Ask".

If you want to jump through hoops to turn JavaScript into something it isn't, you may be unhappy with the result. So instead, you could pick any of the available languages that compile to JavaScript but are closer to what you might want a programming language to look like (Haxe, ParenScript, TypeScript, CoffeeScript, ScriptSharp, Dart, Java (through GWT), C/C++ (through Emscripten) ... in fact almost any other popular language can be translated to JavaScript with varying quality).

But if you use JavaScript for what it is, you will find a language that allows "class-oids", mixins/traits, AOP and what not. More often than not, you will realize than limiting yourself to Java-esque idioms might not be the best idea. Nonetheless, they undoubtedly come in handy at times.

2
  • 1. I'm not sure why you talk here about classes. I didn't mention classes, because they're not a built in concept in JS. 2. I don't care about access control, much like Python's "We're all consenting adults here". The main problem with pseudo-privateness in JS (underscore prefix) is that it's bad for minification efficiency, which is important for us. 3. I'm afraid I don't understand what you are trying to tell here. About the rest of your answer: I think I agree here: approximating Java-style OOP in JS makes things weirder than just adhering to JS's true, but potentially confusing, nature.
    – Stefaan
    CommentedMay 15, 2013 at 20:27
  • 2
    @Stefaan: 1. "[...] a lot of code is written in OOP style (using Prototype's Class.create)" - so you do talk of classes and you seem to assume mimicking them to be "OOP style". 2. "The main problem with pseudo-privateness in JS (underscore prefix) is that it's bad for minification efficiency" - that's a property of the minifier and not of JavaScript. Closure can be made to get rid of underscores. 3. You judge object orientation "from wading through the [...] implementation", all the while object orientation is all about interfaces.
    – back2dos
    CommentedMay 16, 2013 at 5:07
0

One observation from wading through the prototype based implementation is that a lot of code is written in OOP style (using Prototype's Class.create), but the code is not "object oriented" in spirit. The general pattern I've seen: one "constructor" which you are expected to call (but not call twice, because the constructor uses hardcoded DOM id's), a bunch of other "functions" and event handlers, which you are not expected to call (but the because there is no "private" in JavaScript, you don't know that) and data sharing between all these functions through this. Seen from the caller's point of view there is just one "callable" and nothing else.

Not every Javascript project needs OOP. I wouldn't go there unless I were using an existing OO framework like ExtJS. In your case, where it seems the only use of OOP is misuse, I think you should skip it entirely. Since you are switching to jQuery, just follow the jQuery plugin architecture. Write custom plugins when convenient.

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.