Jump to navigation

Code patterns

Module pattern

Features

  • Allows for public and private methods
  • IIFE to create a closure that protects variables and methods, returns an object
  • Less clutter in global namespace

Cons

  • If you try to call a public function from a public function you will run into the function is not defined error - you can solve this error by referencing the name of main object, but - in addition to being annoying and error prone - if you want to move the function to be private you would need to update everything again
ModulePattern = (() => {
  
  const name = 'George';

  function init() {
    console.log(`this is private, ${name}`);
  }

  return {
    settings: [true, false, true],
    speak: (string) => {
      string = string || 'Hello dear.'
      console.log(string);
    },
    doSpeak: () => {
      ModulePattern.speak();
    },
    doSpeak2: () => {
      this.speak();
    },
    doInit: () => {
      init();
    }
  };
  

})();

console.log(ModulePattern);
console.log(ModulePattern.settings);
ModulePattern.speak('something');
// Won't work as not public
ModulePattern.init();
// Can't reference public function - speak is not defined
ModulePattern.doSpeak();
// Will work as referencing the object
ModulePattern.doSpeak2();

ES6

In ES6 the export/import mechanism is used to implement modularity.

// Slider.js
export default class Slider {
    constructor(name) {
        this.name = name;
    }
}

// main.js
import Slider from '/slider';

let slider1 = new Slider('Slider 1');

Revealing Module pattern

Features

  • Looks cleaner than the Module pattern
  • Allows public methods to be called from public methods - since they're all private - unlike the module pattern

Cons

  • Problems extending or patching our private variables/functions
RevModulePattern = (function() {

  let settings = [true, false, true];

  function init() {
    console.log('private');
  }
  
  function speak(string) {
      console.log(string);
  }
  
  function speakSettings() {
      console.log(settings);
  }
  
  function trySpeak(string) {
      speak('Hello');
  }
  
  function changedMindMakePrivate() {
      console.log('private info');
  }

  return {
    settings: settings,
    speak: speak,
    trySpeak: trySpeak,
    speakSettings: speakSettings,
    // Can easily change public/private
    // changedMindMakePrivate
  };
  

})();


console.log(RevModulePattern.settings);
RevModulePattern.speak('hello');
// Can access public methods from public methods
RevModulePattern.trySpeak();

// Even though we change the settings the funciton still 
// retrurns [true, false, true] from the original data
// this is the same if we try patch functions
RevModulePattern.settings = [true];
RevModulePattern.speakSettings();

Creating multiple instances

const revealed = function () {
    var a = [1, 2, 3];
    var b = 'test';
    function abc() {
        return (a[0] * a[1]) + a[2];
    }

    return {
        b: b,
        name: 'revealed',
        abcfn: abc
    };
};

var a = new revealed();
var b = new revealed();
b.b = 'Shane';

console.log(a, b);

Constructor Design Pattern

Features

  • Encapsulation
  • this refers to new object
  • Have types, eg can check instanceof

Cons

  • Needs New keyword
class constructorPattern {
  
  constructor(settings) {
    this.settings = settings;
  }
  
  speak(string) {
    console.log(string);
  }
  
  trySpeak(string) {
    this.speak('Hello');
  }

};

const a = new constructorPattern([true, false, true]);
console.log(a.settings);
a.speak('hello');
a.trySpeak();

Refs