0

For the longest time i have been doing JavaScript classes by doing the following

function MyClass(){
    this.v1;
    this.foo = function(){
        return true;
    }
};

Then i found TypeScript and it looks like it compile its Classes down to

var MyClass = (function () {
    function MyClass(message) {
        this.v1 = message;
    }
    MyClass.prototype.foo = function () {
        return "Hello, " + this.v1;
    };
    return MyClass;
})();

Another Method i have found a lot on the web is

var MyClass = {
    v1:1,
    foo: function(){
       return true;
    }
};

This looks ugly to me but maybe i'm missing something beneficial with this method, as it looks to be the way most people on the web do objects in javaScript.

The first method i'm able to do inharitance from a function i made.

Function.prototype.extends = function(parent){
    this.prototype = new parent();
    this.prototype.constructor = this;
};

I have also seen many other methods on making classes in JavaScript. I would like to know if my method is wrong or if there is a best practice method in doing OOP. All of my projects I have done use the first example. You can see on https://github.com/Patrick-W-McMahon now that I see what JavaScript compilers are doing i'm starting to question my methods. I would like to know what other JavaScript programmers advise is the best method and if there is a difference between the methods. I came from a C++/Java background and as such I write my JavaScript to match my background.

Patrick W. McMahon
  • 3,488
  • 1
  • 20
  • 31
  • 1
    there are a million different ways to do "OOP" in js; all have minor advantages and disadvantages, but seldom would those diffs stack up to make something "right" or "wrong". your code is probably more like what Brendan had in mind than typescript's version. – dandavis Jul 28 '14 at 19:52
  • possible duplicate of [Why does TypeScript mix the module and prototype pattern?](http://stackoverflow.com/questions/14312955/why-does-typescript-mix-the-module-and-prototype-pattern) – cookie monster Jul 28 '14 at 20:05
  • Both should work, but using `prototype` is more standard. – David Knipe Jul 28 '14 at 20:13
  • with first example you can't achieve inheritance or polymorphism. for example all objects created by new(MyClass) would be inhereted from object and nothing else. – webduvet Jul 28 '14 at 20:14
  • would it be different to have this.foo() vs this.prototype.foo() – Patrick W. McMahon Jul 28 '14 at 21:03
  • You may be interested to know what prototype is and how it's used and what a constructor function is and how it's used, explained in detail here: http://stackoverflow.com/a/16063711/1641941 The Douglas Crockford `extends` code is faulty in 2 ways: 1. Modifying objects you don't own (Function) so breaking encapsulation 2. Creating an instance of Parent to be used as Child's prototype. – HMR Jul 29 '14 at 02:11
  • `this.prototype.foo()` wouldn't work. `prototype` is a field of the constructor, not the object. You could use `this.__proto__.foo()`, although I think using `__proto__` is now discouraged. – David Knipe Jul 29 '14 at 07:26

3 Answers3

1

What you read here is called the power constructor, more about it here:

Douglas Crockford about Inheritance


As a multi-paradigm language JavaScript lends itself very well to these different considerations. The truth is, it molds around your brain the way you can conceive it.

In other words, if you can reason about your structure in one way, than use it that way.

If you, on the other hand, want to be completely "free" of your own constraints, then you should abandon reasoning in classes altogether and embrace prototypal inheritance without any thing that resembles a class at all. Duck typing is then a natural consequence and in the extreme you'd use closures all over the place.

What I often do is this:

function myItemBuilder(p1)
{
  var s0, p0 = 0;

  // s0 is a shared private property (much like static in classes)
  // p0 is a shared private property but will be factorized (rendered non-shared)
  // p1 is a private instance property

  return (function (p0) { // factorize p0 if necessary

    return {
      publicProperty : 3,
      method1 : function (arg1) {
        // code here (may use publicProperty, arg1, s0, p0 (factorized) and p1)
      },
      method2 : function (arg2) {
        // code here (may use publicProperty, arg2, s0, p0 (factorized) and p1)
      }
    };
  }(p0++)); // on each invocation p0 will be different and method1/method2 will not interfere across invocations (while s0 is shared across invocations)
}

EDIT: The internal closure is only required if you need to factorize p0 (i.e. have separate, independent values for p0 on each invocation). Of course, if you don't need p0 factorized omit the internal closure.

The above example is intentionally more complex than required to illustrate various interesting cases.

Invoking this method like myItemBuilder("hello") builds a new item that has those specific features but there really is no class construct per se.

This is an especially powerful way of getting instances when you want to abandon classical inheritance. For example in C++ you can inherit from more than one class, which is called a mix-in. In Java and C# you only have single-inheritance but interfaces come to your help.

Here, what I've shown above, is the assembly line metaphor which can assemble components into an instance, with the result that there is no concrete (1) difference between class, interface and mix-in. They are all just instances that have features you can reflect upon through meta-programming (duck typing, reflection/inspection). There still is a logical (2) difference in that: (1) concrete instances behave the same independently of the way they come to being but (2) logically an interface is a contract while an instance is an implementation.

If you really understand SOLID and the Assembly Line Metaphor all of this makes sense. Otherwise I beg your pardon for this long answer :)

ADDED:

With this approach you can't check types, but you don't need to because duck typing allows you to find the method you need without having to look at a class or interface contract. This is similar to having each method in a separate single-method interface.

pid
  • 11,472
  • 6
  • 34
  • 63
  • Thinking of Objects like this is going to take some time. I will be reviewing this post to see if i fully grasp it. Is this much like java factory? – Patrick W. McMahon Jul 28 '14 at 20:27
  • *Concrete Factory* and *Abstract Factory* are creational GoF patterns. I guess a *java factory* is an implementation of one of those two. The Assembly Line Metaphor is very similar, but it is not *just* a pattern, it is part of the prototypal inheritance paradigm. If all of this does not make sense don't be afraid, just use JS the way you know it, because the most important thing is that you understand and are able to maintain your own code. If you don't know what you're doing, nobody does :) – pid Jul 28 '14 at 20:31
  • what is with the }(p1)); at the end of the function doing? the function has (p1) at the beginning. but i don't know what the one at the end is doing. – Patrick W. McMahon Jul 28 '14 at 20:56
  • It invokes the just-defined *function*. The true name is [Closure](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) <- click this. An example is this: `function (x) { /*do smthg*/}(3);`. This invokes the anonymous `function` passing `3` for the argument `x`. As it is anonymous, there's no way you can invoke it anywhere else. – pid Jul 28 '14 at 21:03
  • so its much like java's way of doing foo(x=3){/*do smthg */} would this be a correct assumption? – Patrick W. McMahon Jul 28 '14 at 21:07
  • No it's more like a lambda. In Java you would write `x -> /*do smthg with x*/`. – pid Jul 28 '14 at 22:00
  • Please don't refer to the Crockford article as a good article for classical inheritance. He does it wrong and them blames JavaScript for his own faulty code `Function.method('inherits', function (parent) { this.prototype = new parent();` 1. breaks encapsulation by modifying an object he doesn't own (Function.prototype) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain#Bad_practice.3A_Extension_of_native_prototypes 2. Creating an instance of Parent to be used as prototype of Child. There are tons of examples that are better then that one – HMR Jul 29 '14 at 02:17
  • `What I often do is this:` So you often don't use the prototype chain? Why use 2 functions to create an instance? You can have myItemBuilder return the object literal with p0 and p1 in the closure scope of the object literal's methods. – HMR Jul 29 '14 at 02:22
  • In fact the article I point to is not an example of classical inheritance. It rather is an anti-example, with the intention of promoting prototypal inheritance. The code above has flaws, I know. I'll fix it now :) – pid Jul 29 '14 at 13:39
0

This is explained here

http://www.2ality.com/2011/06/coffeescript-classes.html

A normal JavaScript class definition, wrapped in an IIFE [3]. There is no benefit for using an IIFE here, apart from having a single assignment (which would matter in an object literal, but doesn’t here).

Wiktor Zychla
  • 47,367
  • 6
  • 74
  • 106
0

its a matter of personal preference. Using this method

var MyClass = {
    v1:1,
    foo: function(){
       return true;
    }
};

results in fewer characters and thus smaller JS files so it is the method I usually go with but there is no wrong or right way. Btw. since you commented about this sort of object construction to be ugly you may want to stick with what you are used to. However if you are feeling adventurous check out this project.

It makes oop in javascript quick and painless and MUCH less ugly. Plus it supports multiple inheritance correctly.

dss
  • 470
  • 5
  • 12