
A minimalist approach to OOP in Javascript - J3L2404
http://www.gabordemooij.com/articles/jsoop.html
======
sktrdie
There are so many wrong things about this article, I don't even know where to
start.

* Every time you call createNew(), all the methods and all the properties are re-allocated. This is bad for performance and memory consumption. This is why properties and methods should be added to the "prototype" of an object, so that they don't get re-allocated every time you want to create an instance.

* The inheritance example is not actually inheritance but composition. They are two separate things: <http://www.artima.com/designtechniques/compoinh.html>

* Stuffing everything inside a createNew() function is not minimalist, it's just bad code.

* It refers to "this", "new" and "prototype" as "confusing JS stuff". This obviously means he/she doesn't know anything about the JavaScript programming language.

* JavaScript provides a basic keyword called "new" that easily lets you create a new object. Changing the API naming convention to something called "createNew", is bad practice and will confuse developers trying to use your code. Stick with "new".

If you write code this way, not only it will quickly become slow, but it will
also become hard to have other developers contribute to your code base because
of the weird conventions.

If you want to write __real __minimalist JS code, try reading Eloquent
JavaScript instead:<http://eloquentjavascript.net/>

~~~
gabordemooij
* Yes createNew is not very optimal, in practice this is not really an issue though. Furthermore I value maintainability over performance.

* They share the same object, so it's not composition. Does it really matter that it is not 'pure' inheritance?

* createNew() - bad code? why? just an opinion.

* I have written JS apps from day 1. And yes I know how to handle this,new and prototype. Still, I choose no longer to.

* obj.new() can be confused with new obj(); That's why I have chosen a more distinctive method name; createNew.

~~~
stephenr
> I have written JS apps from day 1. And yes I know how to handle this,new and
> prototype. Still, I choose no longer to

And yet you claim:

> I dont use new, prototype and this because I find them confusing

> obj.new() can be confused with new obj(); That's why I have chosen a more
> distinctive method name; createNew

Also, "dog" can be confused with "do", and "ford" confused with "for" - i
can't count how many time's i've got syntax errors because my dog loop of
nested ford loops just kept outputting "dogs can't drive, stupid" to the
console.

------
stephenr
I really don't understand the great lengths people go to, to avoid the "new"
operator in JavaScript.

This example is horrendous IMO. One of the biggest strengths of JS is the use
of prototypes, but people still persist with shit like returning object
literals with methods directly defined on them..

~~~
TazeTSchnitzel
Well, constructor functions called without the new operator have disastrous
effects. Although that's probably not the prime motivation.

There's several different OOP styles in JS, and I quite like this one. Not
using prototypes means you can create uncompromisable objects with
inheritance.

~~~
stephenr
It's fairly trivial to check if a constructor was called without the new
operator.

------
gabordemooij
I dont use new, prototype and this because I find them confusing. While it may
be trendy and cool to claim that this is just me being stupid and you being
smart I have seen many disasters happen by people who claim to 'fully
understand' Javascript.

At least this method is clean and maintainable. Why use language constructs
that you don't need? I really dont understand why prototypes and new-keywords
would improve Javascript code. I try to write software that's free of bugs,
software that can be trusted. Simplicity seems a logical strategy.

Unfortunately almost every language today is bloated with features, why can't
we have a minimal language, just like C?

I have explained my point of view more extensively here:
<http://www.gabordemooij.com/articles/fatjs.html>

~~~
TazeTSchnitzel
Whilst I personally don't like using constructors and prototypal inheritance,
I think it would be best if you try to understand something before dismissing
it.

Edit: Just because you don't understand something or refuse to understand it
does not mean you should dismiss it.

~~~
gabordemooij
Why do you assume I don't understand prototypical inheritance? To me this
highlights part of the problem of our community. Once you choose not to use a
certain feature you are being regarded as stupid. What ever happened to the
KISS principle? <http://en.wikipedia.org/wiki/KISS_principle>

The minimal approach is simpler. Try explaining prototype OOP and minimal OOP
to a newcomer and see for yourself. Software complexity is a result of
evolution; as the code base grows it becomes more complex, there is no need
for us to add it beforehand.

~~~
stephenr
Simpler isn't always better.

If your entire team is entry level developers who think jquery is magic, maybe
you have a point, but frankly I'd rather work alone that with people that
dense.

~~~
gabordemooij
No. Just no. Simpler is better, especially if there are no real drawbacks.

I think this remark about entry level developers is snobistic.

I have an open mind and I am always willing to learn. Yet you just dismiss my
approach without providing solid argumentation. The only real argument against
the minimalist approach is performance and I was well aware of this when I
wrote the article.

And yes, prototypes are more difficult, not just for entry level developers,
let's see why:

* you cannot use previous OOP experience (aka 'transfer')

* there are MANY ways to do OOP using prototypes (functions,direct prototyping,__proto__) vs ONE

* 'this' has different meanings depending on context -> requires you to process contextual information

* prototypes make existing objects unreliable -> requires prior knowledge about libraries and APIs (leaky abstraction)

* building an object with prototypes requires far more mental steps: you have to know about objects, functions but also about the prototype chain, the hidden prototype property (why?), the logic behind the new keyword etc. If prototypes had been implemented in a very consistent way (without the new-keyword and only using __proto__) I would have advocated prototypes instead of literals.

On top of this, many different 'sugar' solutions exist, most of them
incompatible.

Advantages of the minimalist approach:

* conforms to established industry and business standards in OOP

* requires less knowledge about language details, this leaves much more room to focus on application logic and design

* very transparent, no sugar code (beget) or libraries required

* neat code: methods are grouped together

* allows to implement well known design patterns easily

* protection against corruption of existing objects

* no this, that or self variables

And all you are saying is: it's too easy, it must be for entry level
developers. I mean... what is this about? Are we trying to build great
products or is this some kind of puzzle contest? If you like complexity so
much I recommend to write your next project in malbolge
(<http://en.wikipedia.org/wiki/Malbolge>).

~~~
russfrank
Your approach is essentially the 'module pattern'. This article describes some
other reasons you might not want to use it:
[http://snook.ca/archives/javascript/no-love-for-module-
patte...](http://snook.ca/archives/javascript/no-love-for-module-pattern)

I lead a somewhat large (~10000 sloc) project which uses the module pattern
everywhere. I think the best argument against the module pattern is the
difficulty of debugging. I can no longer just pop open a console and inspect
objects.

Responses to your individual points:

>> * you cannot use previous OOP experience

While unfortunate I believe this is largely unavoidable. Javascript's object
system is not 'classical' inheritance. The module pattern, however, is also
not 'classical' inheritance. Regardless of OOP technique, the New Javascript
Programmer must learn about the object system.

>> * there are MANY ways to do OOP using prototypes

There are also many forms of the module pattern. You just showed me another
one I hadn't seen before. Then there's immediately invoking function
expressions, which some people like to do like this

(function () { var exports = {}; return exports; })());

and others like to do like this

!function() { var private = 4; return { getPrivate: function () { return
private; }; }();

>> * 'this' has different meanings depending on context

Can't argue against this one.

>> * prototypes make existing objects unreliable -> requires prior knowledge
about libraries and APIs (leaky abstraction)

I'm not sure I see the argument here.

>> * building an object with prototypes requires far more mental steps: ..

I'm not sure you really need to know about all of these things.. but sure,
prototypal inheritance is confusing to those with a 'classical' background.

As for the advantages:

>> * conforms to established industry and business standards in OOP

I don't see why prototypal inheritance does not. If you look at CoffeeScript,
it even appears classical.

>> * requires less knowledge about language details

I have to disagree here. Explaining object literals and immediately invoking
functions and closure isn't all that easy.

>> * very transparent, no sugar code or libs required

That's true.

>> * neat code

There's no reason why new/this/prototypal code can't be neat!

>> * design patterns blah blah

There's no reason why new/this/prototypal code can't do design patterns!

>> * protection against corruption

I've never seen this as an issue in practice, but my code isn't running in the
browser. Unless you're talking about protection from other programmers, in
which case, I would quote Guido van Rossum.

>> * no this, that or self variables

Could be a good thing or a bad thing. This means that you have to know what's
public and what isn't, rather than it being explicit. I rather like it when
things are explicit.

Sometimes we sacrifice a little simplicity for a little flexibility or a
little efficiency. Sometimes it's worth it, sometimes it isn't.

~~~
gabordemooij
It all boils down to maintainability. In my experience the minimalist approach
solves much of the complexity of JS by eliminating some features that are not
required (performance might be an issue but never had any problems with it in
practice).

So why am I not allowed to share something that works just because it may not
fully comply with the 'preferred javascript style culture'?

What is this about?

~~~
russfrank
Nobody said you aren't allowed to share it, I simply disagree with you. As I
said, I use a very similar pattern in a large project; I've used
new/this/prototypal style OOP in other projects; and I prefer the traditional
new/this/prototypal style.

------
TazeTSchnitzel
So you basically just came up with what Crockford calls the 'Functional'
method of creating objects?

Why duplicate effort in describing the concept?

~~~
gabordemooij
No, it isnt. It's cleaner because the class-object is an object instead of a
function, this makes it possible to add static methods.

~~~
stephenr
You can have "static methods" on a prototype constructor.

Functions are objects, so adding a static property to a constructor function
is no harder than adding it to an object literal.

~~~
gabordemooij
Yes it is, because you can not add them in the function body:

cls = function(){} cls.staticMethod = function(){}

vs

cls = { staticMethod:function(){} }

I prefer the latter because the static method can be defined within the body
of the 'class' definition. Using the former method it's too easy to add static
methods in different places.

~~~
stephenr
By definition the concept provided means you can't have "static methods".

You get an instance of your "class" by calling createNew(), which returns an
object literal it just created.

This object literal has methods attached to it, but you can't call them before
you "instantiate" an "instance" by calling createNew(), so you don't have any
static methods at all - just a heap of "instance methods" that may or may not
operate on the instance.

Using a Prototype "class" you can very easily have true "static" and
"instance" methods, that are called without and with an instance respectively.

Also, I have no idea what you mean by "add static methods in different
places"?? You either:

* add a method to the constructor directly, which makes it static
    
    
        FooConstructor.method = function () {...};)
    
     * or you add it to the constructor's prototype, which makes it an instance method
    
        FooConstructor.prototype.method = function () {...};

~~~
gabordemooij
I mean that with the minimalist approach you can define static methods in your
'class' body, thus grouping them neatly together:

MyClass = { getInstance: function(){ ... } }

vs

MyClass = function(){ }

//outside function body... MyClass.prototype.getInstance = function(){ ... }

~~~
stephenr

        MyClass = function(){ }
        //outside function body... MyClass.prototype.getInstance = function(){ ... }

but this makes no sense - why would you have a "static" method defined as an
instance method?

in this example you would do:

    
    
        var MyClass = function (){}; // constructor
    
        MyClass.getInstance = function (){}; // static method
    
        MyClass.prototype.start = function (){}; // instance method

~~~
gabordemooij
I think the nested notation is simply more maintainable.

MyClass = {

    
    
       staticMethod: function(){
    
       }
    
       createNew: function() {
    
            obj = {};
    
            obj.instanceMethod = function(){}
    
            return obj;
    
       }   
    

}

Also, I find it quite elegant to see that the constructor function (factory
method) is implemented as a static method as well). Of course I know these
aren't static methods like in Java/PHP but in practice they can treated as
such.

~~~
stephenr
> I think the nested notation is simply more maintainable

why though? I don't see how being part of an object literal is inherently more
maintainable?

> Also, I find it quite elegant to see that the constructor function (factory
> method) is implemented as a static method as well)

but you were harping on about "OOP standards" and "best practices" before -
since when is the constructor for a class a static method? In a language with
true classes, even with a Singleton, the constructor is an instance method.

~~~
gabordemooij
Uhm, no... <http://php.net/manual/en/language.oop5.patterns.php>

A singleton uses a static factory method in PHP and Java. AFAIK there is no
(mainstream) language where a singleton is an instance method.

~~~
stephenr
No, a singleton still _has_ a constructor though - it's just not public. It's
called when the factory method creates a new instance. the factory static
method is NOT the constructor.

~~~
gabordemooij
Yes this is correct. The constructor in a singleton pattern is private. I
meant the way to obtain an instance is the same. Sorry for my mistake.

------
huskyr
I don't really get why you would need a createNew() method in this setup. Why
not simply have a function that returns an object?

function Cat() {

    
    
       var private;
    
       function meow() {
          alert('meow');
       }
    
       return {
          meow : meow
       };

}

var cat = Cat();

~~~
chrisbroadfoot
> Note that we did not use a lot of confusing JS stuff: no this, no new, no
> prototype

Makes as much sense to me as it did to you. That is, very little.

I wish the author would properly explain why he went to great lengths to avoid
the tools available to him.

~~~
TazeTSchnitzel
I don't know the author's reasoning, but I read Crockford's JavaScript: The
Good Parts, which demonstrates several OOP styles (including this one).

One of the reasons he likely didn't use the "this" keyword is because it's
compromisable. "this" is anything that the invoker of the method wants it to
be, so you can accidentally compromise information.

Also, if you have your variables in function scope and the function is created
in that scope, the keyword is unnecessary.

Regarding not using new/constructor functions, some people think the non-
constructor-based OOP model in JS is nicer.

Finally, regarding lack of prototypes, if you want to keep secrets then you
can't re-use functions. On the other hand, if you are creating public/non-
privileged methods, no reason not to re-use functions.

------
tszming
I would recommend the doc from Mozilla (also minimalist):
[https://developer.mozilla.org/en/Introduction_to_Object-
Orie...](https://developer.mozilla.org/en/Introduction_to_Object-
Oriented_JavaScript)

------
mistercow
> no this, no new, no prototype. Therefore this approach is not only easy,
> minimalist and elegant but it also works in the most ancient and exotic
> browsers.

You mean ones with broken JS implementations?

~~~
gabordemooij
Yes, it might help you in daily work environments.

~~~
mistercow
I get your jab about all JS implementations being somewhat broken (what
complex system isn't?), but there's "broken", and then there's "broken to the
point of not supporting core language features".

------
Jebus
Oh no, please not another OOP javascript tutorial without prototypes.

~~~
TazeTSchnitzel
What's wrong with not using prototypal inheritance? There are several styles
of JavaScript OOP. You don't have to use constructor functions.

Unless you mean the .prototype property, in which case you really mean re-use
of functions. That's something you can only use for unsafe public methods,
unfortunately. For safe (uncompromisable) public methods it can't be used, nor
can it for private or privileged methods.

