DEV Community

Cover image for Top 10 JavaScript Patterns Every Developer Likes
Shijie Zhou
Shijie Zhou

Posted on • Updated on

Top 10 JavaScript Patterns Every Developer Likes

1. The constructor Pattern

In classical object-oriented programming languages, a constructor is a special method used to initialize a newly created object once the memory has been allocated for it. In JavaScript almost everything is an object, we have most often interested in object constructors. Since object constructors are used to creating specific types of objects, for example, both preparing the object for use and accepting arguments a constructor can use to set the values of member properties and methods when the object is first created.

As we saw know JavaScript does not support the concept of classes, so inside a constructor, the keyword this references the new object that's being created revisiting object creation, a basic constructor may look as follows:

function Car(model, year, miles) {
  this.model = model;
  this.year = year;
  this.miles = miles;
}

// Usage:
var bmw = new Car('M4', '2019', '1000');
Enter fullscreen mode Exit fullscreen mode

2. The module Pattern

Modules are an integral piece of any robust application's architecture and typically help in keeping the unit of code for a project cleanly separated and organized
There are several option for implementing modules. These include:

  • Object literal notation
  • The module Pattern
  • AMD modules
  • CommonJS module
  • ECMAScript Harmony modules

Object literals :

var newObject = {
  variableKey: variableValue,
  functionKey: function() {
    //…
  }
};
Enter fullscreen mode Exit fullscreen mode

The modules Pattern:

Let's begin looking at an implementation of the Module pattern by created a module that is self-contained.

var testModule = (function() {
  var counter = 0;
  return {
    incrementCounter: function() {
      return ++counter;
    },
    resetCounter: function() {
      counter = 0;
    }
  };
})();

// Usage:
testModule.incrementCounter();
testModule.resetCounter();
Enter fullscreen mode Exit fullscreen mode

3. The Revealing Module Pattern

One thing that the revealing module can do is avoiding repeat the name of the main object when we want to call one public method from another or access public variables.

var myRevealingModule = (function() {
  var privateVariable = 'not okay',
    publicVariable = 'okay';
  function privateFun() {
    return privateVariable;
  }

  function publicSetName(strName) {
    privateVariable = strName;
  }

  function publicGetName() {
    privateFun();
  }

  return {
    setName: publicSetName,
    message: publicVariable,
    getName: publicGetName
  };
})();

//Usage:

myRevealingModule.setName('Marvin King');
Enter fullscreen mode Exit fullscreen mode

4. The Singleton Pattern

The Singleton pattern is thus known because it restricts instantiation of a class to single object. Singletons differ from static classes as we can delay their initialization. generally because they require some information that may not be available during initialization time. For code that is unaware of a previous reference to them, they do not provide a method for easy retrieval. Let's have a look of the structure of singleton:

var singletonPattern = (function() {
  var instance;
  function init() {
    // Singleton
    function privateMethod() {
      console.log('privateMethod');
    }
    var privateVariable = 'this is private variable';
    var privateRandomNumber = Math.random();
    return {
      publicMethod: function() {
        console.log('publicMethod');
      },
      publicProperty: 'this is public property',
      getRandomNumber: function() {
        return privateRandomNumber;
      }
    };
  }

  return {
    // Get the singleton instance if one exists
    // or create if it doesn't
    getInstance: function() {
      if (!instance) {
        instance = init();
      }
      return instance;
    }
  };
})();

// Usage:
var single = singletonPattern.getInstance();
Enter fullscreen mode Exit fullscreen mode

5. The Observer Pattern

The observer is a design pattern in which an object maintains a list of objects depending on it observers, automatically notifying them of any changes to state.

  • Subject
    • Maintains a list of observers, facilities adding or removing observers
  • Observer
    • Provides an update interface for object that need to be notified of a subject’s change of state
  • ConcreteSubject
    • Broadcasts notifications to Observers on changes of state, stores the state of ConcreteObservers
  • ConcreteObserver
    • Stores a reference to the ConcreteSubject, implements an update interface for the observer to ensure state is consistent with subjects
function ObserverList() {
  this.observerList = [];
}

ObserverList.prototype.Add = function(obj) {
  return this.observerList.push(obj);
};

ObserverList.prototype.Empty = function() {
  this.observerList = [];
};

ObserverList.prototype.Count = function() {
  return this.observerList.length;
};

ObserverList.prototype.Get = function(index) {
  if (index > -1 && index < this.observerList.length) {
    return this.observerList[index];
  }
};

//...
Enter fullscreen mode Exit fullscreen mode

When a subject needs to notify observers about something interesting happening, it broadcasts a notification to the observers ( including specific data related to the topic of the notification)

When we no longer wish for a particular observer the notified of changes by the subject it is registered with, the subject can remove it from the list of observers. In the future, I will talk more about the feature of how the observer can be used in JavaScript widely.

6. The Mediator Pattern

If it appears a system has too many direct relationships between components. it may be time to have a central point of the control that components communicate through instead. The mediator pattern promotes loose coupling by ensuring that instead of components referring to each other explicitly.

var mediator = (function() {
  var topics = {};
  var subscribe = function(topic, fn) {
    if (!topics[topic]) {
      topics[topic] = [];
    }
    topics[topic].push({ context: this, callback: fn });
    return this;
  };

  // publish/broadcast an event to the rest of the application
  var publish = function(topic) {
    var args;
    if (!topics[topic]) {
      return false;
    }
    args = Array.prototype.slice.call(arguments, 1);
    for (var i = 0, l = topics[topic].length; i < l; i++) {
      var subscription = topics[topic][i];
      subscription.callback.apply(subscription.content, args);
    }
    return this;
  };
  return {
    publish: publish,
    subscribe: subscribe,
    installTo: function(obj) {
      obj.subscribe = subscribe;
      obj.publish = publish;
    }
  };
})();
Enter fullscreen mode Exit fullscreen mode

7. The Prototype Pattern

One of the benefits of using the Prototype pattern is that we've working with the prototype strengths JavaScript has to offer natively rather than attempting to imitate features of other languages. let's look at the pattern example.

var myCar = {
  name: 'bmw',
  drive: function() {
    console.log('I am driving!');
  },
  panic: function() {
    console.log('wait, how do you stop this thing?');
  }
};

//Usages:

var yourCar = Object.create(myCar);

console.log(yourCar.name); //'bmw'
Enter fullscreen mode Exit fullscreen mode

8. The Factory Pattern

Factory can provide a generic interface for creating objects, where we can specify the type of factory object we wish to create. see the diagram below.

function Car(options) {
  this.doors = options.doors || 4;
  this.state = options.state || 'brand new';
  this.color = options.color || 'silver';
}
Enter fullscreen mode Exit fullscreen mode

9. The Mixin Pattern

Mixins are classes that offer functionality that can be easily inherited by a sub-class or group of sub-classes for the purpose of the function reuse.

var Person = function(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
  this.gender = 'male';
};

var clark = new Person('Clark', 'kent');

var Superhero = function(firstName, lastName, powers) {
  Person.call(this.firstName, this.lastName);
  this.powers = powers;
};

SuperHero.prototype = Object.create(Person.prototype);
var superman = new Superhero('Clark', 'Kent', ['flight', 'heat-vision']);

console.log(superman); //output personal attributes as well as power
Enter fullscreen mode Exit fullscreen mode

In this case, superhero is capable of overriding any inherited values with values specific to its object.

10. The Decorator Pattern

The Decorators are a structural design pattern that aim to promote code reuse. Similar to Mixins, they can be considered another viable alternative to object subclassing. Classically, Decorators offered that ability to add behavior to existing classes in a system dynamically. The idea was the decoration itself wasn't essential to the base functionality of the class. Let's checkout how decorator work in JavaScript

function MacBook() {
  this.cost = function() {
    return 997;
  };
  this.screenSize = function() {
    return 11.6;
  };
}

// Decorator 1

function Memory(macbook) {
  var v = macbook.cost();
  macbook.cost = function() {
    return v + 75;
  };
}

// Decorator 2

function Engraving(macbook) {
  var v = macbook.cost();
  macbook.cost = function() {
    return v + 200;
  };
}

// Decorator 3

function Insurance(macbook) {
  var v = macbook.cost();
  macbook.cost = function() {
    return v + 250;
  };
}

var mb = new MacBook();

Memory(mb);
Engraving(mb);
Insurance(mb);

mb.cost(); // 1522
Enter fullscreen mode Exit fullscreen mode

All the patterns may not use to one project, and some projects may benefit from the decoupling benefits offered by the Observer pattern. That said, once we have a firm grasp-of design patterns and the specific problems they are best suited to. Thus, it becomes much easier to integrate into our application architecture.

Latest comments (28)

Collapse
 
pak11273 profile image
Isaac Pak

All I see is the same regurgitated stuff on every other article about Design Patterns. Car, Person, etc... Can someone please write up something that's practical to Web development for which Javascript is primarily used for?

Collapse
 
mhmreza3623 profile image
mohamadreza

Thanks for sharing this article.
Recently, I had a challenge with javascript and your article could help me.

Collapse
 
shijiezhou profile image
Shijie Zhou

glad that help

Collapse
 
vasilevskialeks profile image
Aleksandar Vasilevsk

Great article, design patterns are very important for every developer. I have a similar article on JavaScript Design Patterns, feel free to check it
codespot.org/javascript-101-design...

Collapse
 
omancoding profile image
OmanCoding

Observer Pattern,
Would not events and event listeners will do the same?

Collapse
 
shijiezhou profile image
Shijie Zhou

Yeah, you can say that the events listeners extends the events. People use that as pattern for their purpose.

Collapse
 
ayuthmang profile image
Ayuth Mangmesap • Edited

Thanks for a good article, the macbook constructor in Decorator Pattern is mistyping it should be 'return' instead of 'reutnr'.

Collapse
 
shijiezhou profile image
Shijie Zhou

Nice catch, we had fixed that already :)

Collapse
 
chubas profile image
Rubén Medellín

The patterns are good. The code examples, uh, they're not.

The decorator pattern as it's shown is a really bad implementation, since you're not wrapping functionality but augmenting the results. You are calling the method cost() where you should be doing something like

Decorator(baseClass){
  orig = baseClass.cost;
  baseClass.cost = () => { return orig() + number; }
}

not call the method at the decoration moment.

I'm not going to point out the errors some othe people already pointed out

Collapse
 
senpl profile image
Michał Urbanek

var myCar = {
name: 'bmw',
drive: function() {
console.log('I am driving!');
},
panic: function() {
console.log('wait, how do you stop this thing?');
}
};

//Usages:

var youcar = Object.create(Car);

console.log(yourcar.name); //'bmw'
I guess it should be var Car or create(MyCar)

Collapse
 
vbarzana profile image
Victor A. Barzana • Edited

I think it's great that you took some time to come up with a post, effort is what matters the most, there will always be haters. I almost forgot that we have been using most of them in our everyday life, now a bit differently with ES6. I would like to recommend two nits:
1- The title should have been: "Top 10 JavaScript Patterns Every Developer Likes"
2- You have a typo declaring the variable publish, this is what you wrote: "var publicsh ...".
3- Other than that I would probably have chosen ES6 to write the article, but good job :)

Collapse
 
shijiezhou profile image
Shijie Zhou

Thank you, I wrote the article very fast, but yeah I updated those typo as well!

Collapse
 
guico33 profile image
guico33

A bunch of outdated code snippets probably taken out from some design pattern book published 10 years ago.

There's really no use for this kind of article. The content isn't original (I've seen those same examples with outdated syntax many times) and there are now much more idiomatic ways to achieve the same things using modern JavaScript.

Collapse
 
tobyfarley_55 profile image
Toby Farley

You would be correct but now with added typos! (i.e The mixin example)

addyosmani.com/resources/essential...

Collapse
 
hyurl profile image
Hyurl

This article must be posted 5 years ago.

Collapse
 
shijiezhou profile image
Shijie Zhou

right!

Collapse
 
sirgalleto profile image
Sebastián Osorio

Just to confirm that you are aware of the ES6 Class support caniuse.com/#feat=es6-class

I do like this post, but "JavaScript does not support the concept of classes" is not a fact since time ago.

Please keep learning and don't stop posting!

Collapse
 
izerozlu profile image
izerozlu

I've come to the discuss section to see this kind of comment. Good pointing!

Collapse
 
drewknab profile image
Drew Knab

They're not really classes.

To quote the caniuse you posted:

ES6 classes are syntactical sugar to provide a much simpler and clearer syntax to create objects and deal with inheritance.

Collapse
 
hyurl profile image
Hyurl

We know JavaScript class is based on prototype, but can someone explain how
different it is than the legacy class in other languages such as Java, Python, C#, PHP, etc. Don’t those languages search properties and methods from a base class (/super class /parent class /prototype, whatever you call it)?

Collapse
 
sirgalleto profile image
Sebastián Osorio

We know that, but the concept of Class exists, and can be used as classes are expected to be used.

Let's not confuse the syntax sugar with the inability to take advantage of them.

Collapse
 
carlillo profile image
Carlos Caballero

I think that patterns are fundamentals to developers. I'm writing a posts series about the 23 traditional patterns explained as I had wish to learn.

Thanks!

Collapse
 
lucasengel profile image
Lucas Engel

Following you for when you post that. =)

Collapse
 
carlillo profile image
Carlos Caballero

Thanks Lucas!

Collapse
 
nitnekb profile image
Quentin

Thx to share this.
We use to work every day with design/architectural patterns without notice it.

Also, sorry to talk about that but there are several typos in your article (even on code examples).
If you are using VSCode like many others, please consider to use a tool such as Spell Right (marketplace.visualstudio.com/items...) ;)

Collapse
 
vbarzana profile image
Victor A. Barzana

Yo, great tip, will recommend it to my Team as well!

Collapse
 
shijiezhou profile image
Shijie Zhou

That's great tools. Thank you Quentin

Collapse
 
smartcodinghub profile image
Oscar

I like the examples and the patterns and how you explained them. I suggest you read about Singleton as an anti-pattern.

P.D.: check the mistakes in the examples, they won't run.