485

I wonder about what the best way is to create an JavaScript object that has properties and methods.

I have seen examples where the person used var self = this and then uses self. in all functions to make sure the scope is always correct.

Then I have seen examples of using .prototype to add properties, while others do it inline.

Can someone give me a proper example of a JavaScript object with some properties and methods?

dakab
  • 5,379
  • 9
  • 43
  • 67
Michael Stum
  • 177,530
  • 117
  • 400
  • 535
  • 14
    There is no "best" way. – Kenan Banks Oct 20 '09 at 16:35
  • Isn't `self` a reserved word? If not, it should be; since `self` is a pre-defined variable referring to the current window. `self === window` – Shaz Apr 13 '11 at 12:09
  • 2
    @Shaz: it's not a reserved word any more than other properties of `window` in the Browser Object Model like `document` or `frames`; you can certainly re-use the identifier as a variable name. Although, yeah, stylistically I prefer `var that= this` to avoid any possible confusion. Even though `window.self` is ultimately pointless so there's rarely any reason to touch it. – bobince Oct 24 '11 at 19:17
  • 7
    When JS is minified, assigning `this` to a local variable (e.g. `self`) reduces file sizes. – Patrick Fisher Mar 17 '13 at 09:11
  • Classjs new link: https://github.com/divio/classjs – Nikola Sep 21 '15 at 12:25

15 Answers15

897

There are two models for implementing classes and instances in JavaScript: the prototyping way, and the closure way. Both have advantages and drawbacks, and there are plenty of extended variations. Many programmers and libraries have different approaches and class-handling utility functions to paper over some of the uglier parts of the language.

The result is that in mixed company you will have a mishmash of metaclasses, all behaving slightly differently. What's worse, most JavaScript tutorial material is terrible and serves up some kind of in-between compromise to cover all bases, leaving you very confused. (Probably the author is also confused. JavaScript's object model is very different to most programming languages, and in many places straight-up badly designed.)

Let's start with the prototype way. This is the most JavaScript-native you can get: there is a minimum of overhead code and instanceof will work with instances of this kind of object.

function Shape(x, y) {
    this.x= x;
    this.y= y;
}

We can add methods to the instance created by new Shape by writing them to the prototype lookup of this constructor function:

Shape.prototype.toString= function() {
    return 'Shape at '+this.x+', '+this.y;
};

Now to subclass it, in as much as you can call what JavaScript does subclassing. We do that by completely replacing that weird magic prototype property:

function Circle(x, y, r) {
    Shape.call(this, x, y); // invoke the base class's constructor function to take co-ords
    this.r= r;
}
Circle.prototype= new Shape();

before adding methods to it:

Circle.prototype.toString= function() {
    return 'Circular '+Shape.prototype.toString.call(this)+' with radius '+this.r;
}

This example will work and you will see code like it in many tutorials. But man, that new Shape() is ugly: we're instantiating the base class even though no actual Shape is to be created. It happens to work in this simple case because JavaScript is so sloppy: it allows zero arguments to be passed in, in which case x and y become undefined and are assigned to the prototype's this.x and this.y. If the constructor function were doing anything more complicated, it would fall flat on its face.

So what we need to do is find a way to create a prototype object which contains the methods and other members we want at a class level, without calling the base class's constructor function. To do this we are going to have to start writing helper code. This is the simplest approach I know of:

function subclassOf(base) {
    _subclassOf.prototype= base.prototype;
    return new _subclassOf();
}
function _subclassOf() {};

This transfers the base class's members in its prototype to a new constructor function which does nothing, then uses that constructor. Now we can write simply:

function Circle(x, y, r) {
    Shape.call(this, x, y);
    this.r= r;
}
Circle.prototype= subclassOf(Shape);

instead of the new Shape() wrongness. We now have an acceptable set of primitives to built classes.

There are a few refinements and extensions we can consider under this model. For example here is a syntactical-sugar version:

Function.prototype.subclass= function(base) {
    var c= Function.prototype.subclass.nonconstructor;
    c.prototype= base.prototype;
    this.prototype= new c();
};
Function.prototype.subclass.nonconstructor= function() {};

...

function Circle(x, y, r) {
    Shape.call(this, x, y);
    this.r= r;
}
Circle.subclass(Shape);

Either version has the drawback that the constructor function cannot be inherited, as it is in many languages. So even if your subclass adds nothing to the construction process, it must remember to call the base constructor with whatever arguments the base wanted. This can be slightly automated using apply, but still you have to write out:

function Point() {
    Shape.apply(this, arguments);
}
Point.subclass(Shape);

So a common extension is to break out the initialisation stuff into its own function rather than the constructor itself. This function can then inherit from the base just fine:

function Shape() { this._init.apply(this, arguments); }
Shape.prototype._init= function(x, y) {
    this.x= x;
    this.y= y;
};

function Point() { this._init.apply(this, arguments); }
Point.subclass(Shape);
// no need to write new initialiser for Point!

Now we've just got the same constructor function boilerplate for each class. Maybe we can move that out into its own helper function so we don't have to keep typing it, for example instead of Function.prototype.subclass, turning it round and letting the base class's Function spit out subclasses:

Function.prototype.makeSubclass= function() {
    function Class() {
        if ('_init' in this)
            this._init.apply(this, arguments);
    }
    Function.prototype.makeSubclass.nonconstructor.prototype= this.prototype;
    Class.prototype= new Function.prototype.makeSubclass.nonconstructor();
    return Class;
};
Function.prototype.makeSubclass.nonconstructor= function() {};

...

Shape= Object.makeSubclass();
Shape.prototype._init= function(x, y) {
    this.x= x;
    this.y= y;
};

Point= Shape.makeSubclass();

Circle= Shape.makeSubclass();
Circle.prototype._init= function(x, y, r) {
    Shape.prototype._init.call(this, x, y);
    this.r= r;
};

...which is starting to look a bit more like other languages, albeit with slightly clumsier syntax. You can sprinkle in a few extra features if you like. Maybe you want makeSubclass to take and remember a class name and provide a default toString using it. Maybe you want to make the constructor detect when it has accidentally been called without the new operator (which would otherwise often result in very annoying debugging):

Function.prototype.makeSubclass= function() {
    function Class() {
        if (!(this instanceof Class))
            throw('Constructor called without "new"');
        ...

Maybe you want to pass in all the new members and have makeSubclass add them to the prototype, to save you having to write Class.prototype... quite so much. A lot of class systems do that, eg:

Circle= Shape.makeSubclass({
    _init: function(x, y, z) {
        Shape.prototype._init.call(this, x, y);
        this.r= r;
    },
    ...
});

There are a lot of potential features you might consider desirable in an object system and no-one really agrees on one particular formula.


The closure way, then. This avoids the problems of JavaScript's prototype-based inheritance, by not using inheritance at all. Instead:

function Shape(x, y) {
    var that= this;

    this.x= x;
    this.y= y;

    this.toString= function() {
        return 'Shape at '+that.x+', '+that.y;
    };
}

function Circle(x, y, r) {
    var that= this;

    Shape.call(this, x, y);
    this.r= r;

    var _baseToString= this.toString;
    this.toString= function() {
        return 'Circular '+_baseToString(that)+' with radius '+that.r;
    };
};

var mycircle= new Circle();

Now every single instance of Shape will have its own copy of the toString method (and any other methods or other class members we add).

The bad thing about every instance having its own copy of each class member is that it's less efficient. If you are dealing with large numbers of subclassed instances, prototypical inheritance may serve you better. Also calling a method of the base class is slightly annoying as you can see: we have to remember what the method was before the subclass constructor overwrote it, or it gets lost.

[Also because there is no inheritance here, the instanceof operator won't work; you would have to provide your own mechanism for class-sniffing if you need it. Whilst you could fiddle the prototype objects in a similar way as with prototype inheritance, it's a bit tricky and not really worth it just to get instanceof working.]

The good thing about every instance having its own method is that the method may then be bound to the specific instance that owns it. This is useful because of JavaScript's weird way of binding this in method calls, which has the upshot that if you detach a method from its owner:

var ts= mycircle.toString;
alert(ts());

then this inside the method won't be the Circle instance as expected (it'll actually be the global window object, causing widespread debugging woe). In reality this typically happens when a method is taken and assigned to a setTimeout, onclick or EventListener in general.

With the prototype way, you have to include a closure for every such assignment:

setTimeout(function() {
    mycircle.move(1, 1);
}, 1000);

or, in the future (or now if you hack Function.prototype) you can also do it with function.bind():

setTimeout(mycircle.move.bind(mycircle, 1, 1), 1000);

if your instances are done the closure way, the binding is done for free by the closure over the instance variable (usually called that or self, though personally I would advise against the latter as self already has another, different meaning in JavaScript). You don't get the arguments 1, 1 in the above snippet for free though, so you would still need another closure or a bind() if you need to do that.

There are lots of variants on the closure method too. You may prefer to omit this completely, creating a new that and returning it instead of using the new operator:

function Shape(x, y) {
    var that= {};

    that.x= x;
    that.y= y;

    that.toString= function() {
        return 'Shape at '+that.x+', '+that.y;
    };

    return that;
}

function Circle(x, y, r) {
    var that= Shape(x, y);

    that.r= r;

    var _baseToString= that.toString;
    that.toString= function() {
        return 'Circular '+_baseToString(that)+' with radius '+r;
    };

    return that;
};

var mycircle= Circle(); // you can include `new` if you want but it won't do anything

Which way is “proper”? Both. Which is “best”? That depends on your situation. FWIW I tend towards prototyping for real JavaScript inheritance when I'm doing strongly OO stuff, and closures for simple throwaway page effects.

But both ways are quite counter-intuitive to most programmers. Both have many potential messy variations. You will meet both (as well as many in-between and generally broken schemes) if you use other people's code/libraries. There is no one generally-accepted answer. Welcome to the wonderful world of JavaScript objects.

[This has been part 94 of Why JavaScript Is Not My Favourite Programming Language.]

bobince
  • 528,062
  • 107
  • 651
  • 834
  • 13
    Very nice gradual step-through from "class" def to object instantiation. And nice touch on bypassing `new`. – Crescent Fresh Oct 21 '09 at 01:02
  • 8
    It seems like JavaScript is not your favorite language because you want to use it as if it had classes. – Jonathan Feinberg Oct 21 '09 at 01:33
  • 61
    Of course I do, so does everyone: the class-and-instance model is the more natural one for a majority of the common problems programmers face today. I do agree that, on a theory basis, prototype-based inheritance can potentially offer a more flexible way of working, but JavaScript totally does not deliver on that promise. Its clunky constructor function system gives us the worst of both worlds, making class-like inheritance hard whilst providing none of the flexibility or simplicity prototypes could offer. In short, it's poo. – bobince Oct 21 '09 at 02:05
  • 2
    There seems to be a lot of misinformation and bad patterns on the Internet and for someone new to javascript, they said confusing and bad precedence. Your answer (especially the last two patterns) really helped me clear up my mind. BTW, these member functions appear as anonymous in debugger, how can you avoid that? – haridsv May 08 '11 at 20:30
  • 2
    @haridsv: in principle by using a named function expression like `x.prototype.doThing= function doThing() { ... };`. Unfortunately, IE<9 [messes them up](http://kangax.github.com/nfe/). – bobince May 09 '11 at 20:04
  • 4
    Bob I think this is an awesome answer - I've been grappling with these two patterns for a while and I think you've coded something more concisely than a Resig and explained with more insight than a Crockford. No higher praise can I think of.... – James Westgate May 17 '11 at 19:29
  • 1
    Function.prototype.makeSubclass() is so much more intuitive, useful, and simple to use, than ECMAScript 5 Object.create()! I wish Douglas Crockford would have read this before pushing Object.create() into the standard. – Jean Vincent Jul 20 '11 at 13:51
  • 3
    @Jean: well, they do different things. `Object.create()` is designed as a low-level language feature to provide access to all the capabilities of ES5 objects, rather than to sanction one particular class/instance implementation. You can certainly build class/instance systems on top of `Object.create()` (indeed, the version of `makeSubclass()` I'm currently using does so, with a shimmed partial implementation of `create()` for ES3 browsers). – bobince Jul 21 '11 at 19:19
  • 2
    ^^ I also use Object.create() mainly because this is in ES5, but I think that the name is wrong - i.e. very poorly describes what it does, prototypeClone() would have been better -. Object.create also erases the constructor property of the target in typical usage patterns, which could have been avoided with a different signature, and it's parameter should be an object, not it's prototype, because most, if not all, usage patterns will require to get the prototype anyway. – Jean Vincent Jul 26 '11 at 14:01
  • 4
    It's always seemed to me that graphing classical inheritance paradigms onto prototypical languages like javascript is a square peg and a round hole. Are there times this is truly necessary or is this just a way for people to ham-fist the language to be the way they want rather than simply using the language for what it is? – slf Oct 24 '11 at 13:50
  • 1
    Since ES6 has come out, the benefit of a nicer syntax using the closure way has disappeared. ES6's syntax is cleaner and nicer and more similar to other conventional oo languages like C++ and Java. But I would still recommend JS programmers to understand how prototype-based inheritance works because ES6 is just syntax sugar, not a new language, under the hood ES6 is transpiled to use the prototype-based inheritance. – Huang C. Apr 16 '17 at 08:48
  • 1
    Instead of `Circle.prototype= new Shape();`, Mozilla suggests to use `Circle.prototype= Object.create(Shape.prototype); Circle.prototype.constructor= Circle;`. [Reference](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance) – Paul Aug 30 '18 at 08:23
90

I use this pattern fairly frequently - I've found that it gives me a pretty huge amount of flexibility when I need it. In use it's rather similar to Java-style classes.

var Foo = function()
{

    var privateStaticMethod = function() {};
    var privateStaticVariable = "foo";

    var constructor = function Foo(foo, bar)
    {
        var privateMethod = function() {};
        this.publicMethod = function() {};
    };

    constructor.publicStaticMethod = function() {};

    return constructor;
}();

This uses an anonymous function that is called upon creation, returning a new constructor function. Because the anonymous function is called only once, you can create private static variables in it (they're inside the closure, visible to the other members of the class). The constructor function is basically a standard Javascript object - you define private attributes inside of it, and public attributes are attached to the this variable.

Basically, this approach combines the Crockfordian approach with standard Javascript objects to create a more powerful class.

You can use it just like you would any other Javascript object:

Foo.publicStaticMethod(); //calling a static method
var test = new Foo();     //instantiation
test.publicMethod();      //calling a method
ShZ
  • 6,518
  • 1
  • 26
  • 22
  • 4
    That looks interesting, because it's rather close to my "home-turf" which is C#. I also think I start to understand why privateStaticVariable is really private (as it's defined within the scope of a function and kept alive as long as there are references to it?) – Michael Stum Oct 20 '09 at 22:05
  • 4
    Problem here is that every object gets its own copy of all private and public functions. – virtualnobi Sep 12 '13 at 11:51
  • 2
    @virtualnobi: This pattern doesn't prevent you from writing protytpe methods: `constructor.prototype.myMethod = function () { ... }`. – Nicolas Le Thierry d'Ennequin Feb 17 '14 at 09:42
25

Douglas Crockford discusses that topic extensively in The Good Parts. He recommends to avoid the new operator to create new objects. Instead he proposes to create customized constructors. For instance:

var mammal = function (spec) {     
   var that = {}; 
   that.get_name = function (  ) { 
      return spec.name; 
   }; 
   that.says = function (  ) { 
      return spec.saying || ''; 
   }; 
   return that; 
}; 

var myMammal = mammal({name: 'Herb'});

In Javascript a function is an object, and can be used to construct objects out of together with the new operator. By convention, functions intended to be used as constructors start with a capital letter. You often see things like:

function Person() {
   this.name = "John";
   return this;
}

var person = new Person();
alert("name: " + person.name);**

In case you forget to use the new operator while instantiating a new object, what you get is an ordinary function call, and this is bound to the global object instead to the new object.

Diego Pino
  • 11,278
  • 1
  • 55
  • 57
  • 5
    Is it me or do I think Crockford makes absolutely no sense with his bashing of the new operator? – meder omuraliev Oct 20 '09 at 16:41
  • 3
    @meder: Not just you. At least, I think there's nothing wrong with the new operator. And there's an implicit `new` in `var that = {};` anyway. – Tim Down Oct 20 '09 at 23:04
  • 17
    Crockford is a cranky old man and I disagree with him on a lot, but he is at least promoting taking a critical look at JavaScript and it's worth listening to what he has to say. – bobince Oct 21 '09 at 00:24
  • 2
    @bobince: Agreed. His writing on closures opened my eyes to a lot of stuff about 5 years ago, and he encourages a thoughtful approach. – Tim Down Oct 21 '09 at 08:35
  • 1
    Agree with you guys, Crockford provides and insightful look into Javascript, but some of his tricks/advices don't worth the pain sometimes. Particularly on this topic I still like using **new** to create new objects. – Diego Pino Oct 21 '09 at 23:36
  • 20
    I agree with Crockford. The issue with the new operator is that JavaScript will make the context of "this" very different than when otherwise calling a function. Despite the proper case convention, there are issues that arise on larger code bases as developers forget to use new, forget to capitalize, etc. To be pragmatic, you can do everything you need to do without the new keyword - so why use it and introduce more points of failure in the code? JS is a prototypal, not class based, language. So why do we want it to act like a staticly typed language? I certainly don't. – Joshua Ramirez Jun 30 '12 at 22:38
18

To continue off of bobince's answer

In es6 you can now actually create a class

So now you can do:

class Shape {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }

    toString() {
        return `Shape at ${this.x}, ${this.y}`;
    }
}

So extend to a circle (as in the other answer) you can do:

class Circle extends Shape {
    constructor(x, y, r) {
        super(x, y);
        this.r = r;
    }

    toString() {
        let shapeString = super.toString();
        return `Circular ${shapeString} with radius ${this.r}`;
    }
}

Ends up a bit cleaner in es6 and a little easier to read.


Here is a good example of it in action:

class Shape {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  toString() {
    return `Shape at ${this.x}, ${this.y}`;
  }
}

class Circle extends Shape {
  constructor(x, y, r) {
    super(x, y);
    this.r = r;
  }

  toString() {
    let shapeString = super.toString();
    return `Circular ${shapeString} with radius ${this.r}`;
  }
}

let c = new Circle(1, 2, 4);

console.log('' + c, c);
Community
  • 1
  • 1
Naftali
  • 144,921
  • 39
  • 244
  • 303
6

You can also do it this way, using structures :

function createCounter () {
    var count = 0;

    return {
        increaseBy: function(nb) {
            count += nb;
        },
        reset: function {
            count = 0;
        }
    }
}

Then :

var counter1 = createCounter();
counter1.increaseBy(4);
Eino Gourdin
  • 4,169
  • 3
  • 39
  • 67
  • 6
    I don't like that way because whitespace is important. The curly after the return must be on the same line for cross-browser compatibility. – geowa4 Oct 20 '09 at 19:14
5

Another way would be http://jsfiddle.net/nnUY4/ (i dont know if this kind of handling object creation and revealing functions follow any specific pattern)

// Build-Reveal

var person={
create:function(_name){ // 'constructor'
                        //  prevents direct instantiation 
                        //  but no inheritance
    return (function() {

        var name=_name||"defaultname";  // private variable

        // [some private functions]

        function getName(){
            return name;
        }

        function setName(_name){
            name=_name;
        }

        return {    // revealed functions
            getName:getName,    
            setName:setName
        }
    })();
   }
  }

  // … no (instantiated) person so far …

  var p=person.create(); // name will be set to 'defaultname'
  p.setName("adam");        // and overwritten
  var p2=person.create("eva"); // or provide 'constructor parameters'
  alert(p.getName()+":"+p2.getName()); // alerts "adam:eva"
Fluchtpunkt
  • 447
  • 5
  • 11
5

Creating an object

The easiest way to create an object in JavaScript is to use the following syntax :

var test = {
  a : 5,
  b : 10,
  f : function(c) {
    return this.a + this.b + c;
  }
}

console.log(test);
console.log(test.f(3));

This works great for storing data in a structured way.

For more complex use cases, however, it's often better to create instances of functions :

function Test(a, b) {
  this.a = a;
  this.b = b;
  this.f = function(c) {
return this.a + this.b + c;
  };
}

var test = new Test(5, 10);
console.log(test);
console.log(test.f(3));

This allows you to create multiple objects that share the same "blueprint", similar to how you use classes in eg. Java.

This can still be done more efficiently, however, by using a prototype.

Whenever different instances of a function share the same methods or properties, you can move them to that object's prototype. That way, every instance of a function has access to that method or property, but it doesn't need to be duplicated for every instance.

In our case, it makes sense to move the method f to the prototype :

function Test(a, b) {
  this.a = a;
  this.b = b;
}

Test.prototype.f = function(c) {
  return this.a + this.b + c;
};

var test = new Test(5, 10);
console.log(test);
console.log(test.f(3));

Inheritance

A simple but effective way to do inheritance in JavaScript, is to use the following two-liner :

B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;

That is similar to doing this :

B.prototype = new A();

The main difference between both is that the constructor of A is not run when using Object.create, which is more intuitive and more similar to class based inheritance.

You can always choose to optionally run the constructor of A when creating a new instance of B by adding adding it to the constructor of B :

function B(arg1, arg2) {
    A(arg1, arg2); // This is optional
}

If you want to pass all arguments of B to A, you can also use Function.prototype.apply() :

function B() {
    A.apply(this, arguments); // This is optional
}

If you want to mixin another object into the constructor chain of B, you can combine Object.create with Object.assign :

B.prototype = Object.assign(Object.create(A.prototype), mixin.prototype);
B.prototype.constructor = B;

Demo

function A(name) {
  this.name = name;
}

A.prototype = Object.create(Object.prototype);
A.prototype.constructor = A;

function B() {
  A.apply(this, arguments);
  this.street = "Downing Street 10";
}

B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;

function mixin() {

}

mixin.prototype = Object.create(Object.prototype);
mixin.prototype.constructor = mixin;

mixin.prototype.getProperties = function() {
  return {
    name: this.name,
    address: this.street,
    year: this.year
  };
};

function C() {
  B.apply(this, arguments);
  this.year = "2018"
}

C.prototype = Object.assign(Object.create(B.prototype), mixin.prototype);
C.prototype.constructor = C;

var instance = new C("Frank");
console.log(instance);
console.log(instance.getProperties());

Note

Object.create can be safely used in every modern browser, including IE9+. Object.assign does not work in any version of IE nor some mobile browsers. It is recommended to polyfill Object.create and/or Object.assign if you want to use them and support browsers that do not implement them.

You can find a polyfill for Object.create here and one for Object.assign here.

John Slegers
  • 45,213
  • 22
  • 199
  • 169
4

When one uses the trick of closing on "this" during a constructor invocation, it's in order to write a function that can be used as a callback by some other object that doesn't want to invoke a method on an object. It's not related to "making the scope correct".

Here's a vanilla JavaScript object:

function MyThing(aParam) {
    var myPrivateVariable = "squizzitch";

    this.someProperty = aParam;
    this.useMeAsACallback = function() {
        console.log("Look, I have access to " + myPrivateVariable + "!");
    }
}

// Every MyThing will get this method for free:
MyThing.prototype.someMethod = function() {
    console.log(this.someProperty);
};

You might get a lot out of reading what Douglas Crockford has to say about JavaScript. John Resig is also brilliant. Good luck!

Jonathan Feinberg
  • 44,698
  • 7
  • 80
  • 103
  • 1
    Uh, closing around `this` has everything to do with "making the scope correct". – Roatin Marth Oct 20 '09 at 15:59
  • 3
    Jonathan is right. The scope of a js function is whatever you design it to be. The self=this trick is one way to tie it to particular instance so it doesn't change when called in another context. But sometimes that's what you actually want. Depends on context. – Marco Oct 20 '09 at 17:55
  • I think you're all saying the same thing actually. `self=this` although doesn't force `this` to persist, easily allows "correct" scoping via a closure. – Crescent Fresh Oct 21 '09 at 01:05
  • 2
    The reason you do that=this is to give nested functions access to the scope of this as it exists in the constructor function. When nested functions are inside constructor functions, their "this" scope reverts to the global scope. – Joshua Ramirez Jun 30 '12 at 22:41
4

Closure is versatile. bobince has well summarized the prototype vs. closure approaches when creating objects. However you can mimic some aspects of OOP using closure in a functional programming way. Remember functions are objects in JavaScript; so use function as object in a different way.

Here is an example of closure:

function outer(outerArg) {
    return inner(innerArg) {
        return innerArg + outerArg; //the scope chain is composed of innerArg and outerArg from the outer context 
    }
}

A while ago I came across the Mozilla's article on Closure. Here is what jump at my eyes: "A closure lets you associate some data (the environment) with a function that operates on that data. This has obvious parallels to object oriented programming, where objects allow us to associate some data (the object's properties) with one or more methods". It was the very first time I read a parallelism between closure and classic OOP with no reference to prototype.

How?

Suppose you want to calculate the VAT of some items. The VAT is likely to stay stable during the lifetime of an application. One way to do it in OOP (pseudo code):

public class Calculator {
    public property VAT { get; private set; }
    public Calculator(int vat) {
        this.VAT = vat;
    }
    public int Calculate(int price) {
        return price * this.VAT;
    }
}

Basically you pass a VAT value into your constructor and your calculate method can operate upon it via closure. Now instead of using a class/constructor, pass your VAT as an argument into a function. Because the only stuff you are interested in is the calculation itself, returns a new function, which is the calculate method:

function calculator(vat) {
    return function(item) {
        return item * vat;
    }
}
var calculate = calculator(1.10);
var jsBook = 100; //100$
calculate(jsBook); //110

In your project identify top-level values that are good candidate of what VAT is for calculation. As a rule of thumb whenever you pass the same arguments on and on, there is a way to improve it using closure. No need to create traditional objects.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures

roland
  • 7,695
  • 6
  • 46
  • 61
1

A Pattern That Serves Me Well

var Klass = function Klass() {
    var thus = this;
    var somePublicVariable = x
      , somePublicVariable2 = x
      ;
    var somePrivateVariable = x
      , somePrivateVariable2 = x
      ;

    var privateMethod = (function p() {...}).bind(this);

    function publicMethod() {...}

    // export precepts
    this.var1 = somePublicVariable;
    this.method = publicMethod;

    return this;
};

First, you may change your preference of adding methods to the instance instead of the constructor's prototype object. I almost always declare methods inside of the constructor because I use Constructor Hijacking very often for purposes regarding Inheritance & Decorators.

Here's how I decide where which declarations are writ:

  • Never declare a method directly on the context object (this)
  • Let var declarations take precedence over function declarations
  • Let primitives take precedence over objects ({} and [])
  • Let public declarations take precedence over private declarations
  • Prefer Function.prototype.bind over thus, self, vm, etc
  • Avoid declaring a Class within another Class, unless:
    • It should be obvious that the two are inseparable
    • The Inner class implements The Command Pattern
    • The Inner class implements The Singleton Pattern
    • The Inner class implements The State Pattern
    • The Inner Class implements another Design Pattern that warrants this
  • Always return this from within the Lexical Scope of the Closure Space.

Here's why these help:

Constructor Hijacking
var Super = function Super() {
    ...
    this.inherited = true;
    ...
};
var Klass = function Klass() {
    ...
    // export precepts
    Super.apply(this);  // extends this with property `inherited`
    ...
};
Model Design
var Model = function Model(options) {
    var options = options || {};

    this.id = options.id || this.id || -1;
    this.string = options.string || this.string || "";
    // ...

    return this;
};
var model = new Model({...});
var updated = Model.call(model, { string: 'modified' });
(model === updated === true);  // > true
Design Patterns
var Singleton = new (function Singleton() {
    var INSTANCE = null;

    return function Klass() {
        ...
        // export precepts
        ...

        if (!INSTANCE) INSTANCE = this;
        return INSTANCE;
    };
})();
var a = new Singleton();
var b = new Singleton();
(a === b === true);  // > true

As you can see, I really have no need for thus since I prefer Function.prototype.bind (or .call or .apply) over thus. In our Singleton class, we don't even name it thus because INSTANCE conveys more information. For Model, we return this so that we can invoke the Constructor using .call to return the instance we passed into it. Redundantly, we assigned it to the variable updated, though it is useful in other scenarios.

Alongside, I prefer constructing object-literals using the new keyword over {brackets}:

Preferred
var klass = new (function Klass(Base) {
    ...
    // export precepts
    Base.apply(this);  //
    this.override = x;
    ...
})(Super);
Not Preferred
var klass = Super.apply({
    override: x
});

As you can see, the latter has no ability to override its Superclass's "override" property.

If I do add methods to the Class's prototype object, I prefer an object literal -- with or without using the new keyword:

Preferred
Klass.prototype = new Super();
// OR
Klass.prototype = new (function Base() {
    ...
    // export precepts
    Base.apply(this);
    ...
})(Super);
// OR
Klass.prototype = Super.apply({...});
// OR
Klass.prototype = {
    method: function m() {...}
};
Not Preferred
Klass.prototype.method = function m() {...};
Cody
  • 9,785
  • 4
  • 61
  • 46
1

I'd like to mention that we can use either a Title or a String to declare an Object.
There are different ways on calling each type of them. See below:

var test = {

  useTitle : "Here we use 'a Title' to declare an Object",
  'useString': "Here we use 'a String' to declare an Object",
  
  onTitle : function() {
    return this.useTitle;
  },
  
  onString : function(type) {
    return this[type];
  }
  
}

console.log(test.onTitle());
console.log(test.onString('useString'));
eQ19
  • 9,880
  • 3
  • 65
  • 77
0
var Person = function (lastname, age, job){
this.name = name;
this.age = age;
this.job = job;
this.changeName = function(name){
this.lastname = name;
}
}
var myWorker = new Person('Adeola', 23, 'Web Developer');
myWorker.changeName('Timmy');

console.log("New Worker" + myWorker.lastname);
  • 4
    What does that add to the numerous extensive answers already offered? – blm Nov 19 '15 at 00:00
  • I like this answer as it is concise and shows the three parts of the implementation: 1) Define the object, 2) Instantiate an instance of the object , 3) Use the instance - it shows it all at a glance instead of having the parse through all of the verbose answers above ( which, of course, are all extremely good answers with all of the pertinent details that one would want ) - kind of a simple summary here – G-Man Apr 08 '19 at 15:43
0

In addition to the accepted answer from 2009. If you can can target modern browsers, one can make use of the Object.defineProperty.

The Object.defineProperty() method defines a new property directly on an object, or modifies an existing property on an object, and returns the object. Source: Mozilla

var Foo = (function () {
    function Foo() {
        this._bar = false;
    }
    Object.defineProperty(Foo.prototype, "bar", {
        get: function () {
            return this._bar;
        },
        set: function (theBar) {
            this._bar = theBar;
        },
        enumerable: true,
        configurable: true
    });
    Foo.prototype.toTest = function () {
        alert("my value is " + this.bar);
    };
    return Foo;
}());

// test instance
var test = new Foo();
test.bar = true;
test.toTest();

To see a desktop and mobile compatibility list, see Mozilla's Browser Compatibility list. Yes, IE9+ supports it as well as Safari mobile.

Alex Nolasco
  • 18,750
  • 9
  • 86
  • 81
0

You can also try this

    function Person(obj) {
    'use strict';
    if (typeof obj === "undefined") {
        this.name = "Bob";
        this.age = 32;
        this.company = "Facebook";
    } else {
        this.name = obj.name;
        this.age = obj.age;
        this.company = obj.company;
    }

}

Person.prototype.print = function () {
    'use strict';
    console.log("Name: " + this.name + " Age : " + this.age + " Company : " + this.company);
};

var p1 = new Person({name: "Alex", age: 23, company: "Google"});
p1.print();
G Naga Subrahmanyam
  • 308
  • 1
  • 5
  • 19
-1

Bascially there is no concept of class in JS so we use function as a class constructor which is relevant with the existing design patterns.

//Constructor Pattern
function Person(name, age, job){
 this.name = name;
 this.age = age;
 this.job = job;
 this.doSomething = function(){
    alert('I am Happy');
}
}

Till now JS has no clue that you want to create an object so here comes the new keyword.

var person1 = new Person('Arv', 30, 'Software');
person1.name //Arv

Ref : Professional JS for web developers - Nik Z

Airwind711
  • 120
  • 3
  • Downvote accepted : with a valid reason would have been more informative and would have served an opportunity to improve. – Airwind711 Nov 11 '15 at 04:02
  • There *is* the concept of a `class` in JS, like you mentioned in your heading using the `function` keyword. It's *not* a Design Pattern but an intentional feature of the language. I didn't downvote you on this, but it looks like someone else did because of the terseness and almost irrelevance to the question. Hope this feedback helps. – Cody Feb 26 '18 at 21:41