Practical OOP patterns in JavaScript

Categories: JavaScript

Currently the whole world is crazy about JavaScript. People find themselves write JavaScript more often than ever. To be honest I really enjoy writing JavaScript. I’m also a big fan of design patterns. They simply make my life easier as a developer. Here are some OOP JavaScript patterns I’ve embraced and use in my daily work.

Prototype pattern

This pattern is quite easy and straightforward. We first start with a function which we will later use as a constructor.

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}

As you can see we have defined a function called Person which has two public properties – firstName and lastName. Each instance of that class will store its own firstName and lastName. We want each instance of the class to walk, eat or even speak. Lets define methods which will handle these actions. Since we want these methods to be available for all instances of Person we will use the prototype object of Person and add the methods to it.

Person.prototype.walk = function () {
    alert(this.firstName + ' is walking!');
};

Person.prototype.eat = function () {
    alert(this.firstName + ' is eating!');
};

Person.prototype.speak = function () {
    alert('Hello, my name is ' + this.firstName);
};

And that my friends is the prototype pattern. It’s time to put everything together.

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}

Person.prototype.walk = function () {
    alert(this.firstName + ' is walking!');
};

Person.prototype.eat = function () {
    alert(this.firstName + ' is eating!');
};

Person.prototype.speak = function () {
    alert('Hello, my name is ' + this.firstName);
};

var person1 = new Person('Stefan', 'Staynov');
var person2 = new Person('John', 'Doe');

person1.walk();
person1.eat();
person1.speak();

person2.walk();
person2.eat();
person2.speak();

Lets list some of the benefits of using the prototype pattern.

  • We can define our own complex types and describe their behaviors similar to what we can do in other programming languages.
  • We define different methods using the prototype object. What that means is that each method is located only in one place in memory and all objects use it from there. If we know that we will have a lot of instances of the class, using the prototype pattern will optimize the memory usage.
  • If we use a library which components are built using the prototype pattern we have the ability to customize some of the functionality of these components. We can always override some of the methods.

There are things I don’t really like about the prototype pattern.

  • I cannot define my own private fields or methods which can be accessed from the methods defined through the prototype object. If we use the pattern we need to make everything publicly accessible.
  • It sometimes give us too much freedom. The ability to customize everything that was defined through the prototype pattern sometimes leads to unexpected results, a.k.a. bugs.

There are ways to make something private but we need to sacrifice something else in return. Lets look at the following definition of the Person class.

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;

    function getFullName() {
        return this.firstName + ' ' + this.lastName;
    }

    this.speak = function () {
        alert('Hello, my name is ' + getFullName());
    }
}

Person.prototype.walk = function () {
    alert(this.firstName + ' is walking!');
};

var person = new Person('Stefan', 'Staynov');
person.speak();
person.walk();

When using the class everything seems the same. We were even able to define our own private method which is later used in a public method. Unfortunately, we now have another “issue”. When creating an instance of the Person class we also allocate additional memory for the speak and getFullName methods. And that happens for each instance. We still have the walk method in one place in memory since it uses the prototype object of Person. So keep that in mind when defining methods like eat and getFullName in your own classes.

Revealing Module Pattern

This is another very popular JavaScript pattern. Similar to the Prototype Pattern, it is quite straightforward. It utilizes the Immediately-Invoked Function Expressions or simply IIFE. Some people also refer to it as Self-Executing Anonymous Functions. Using IIFE is all about variable scoping. Variables and functions declared in a self executing function are only available to the code within the self executing function. This allows us to write code without worring how variables are named in other blocks of JavaScript code. It also keeps the global namespace clean and intact. In the case of the Revealing Module Pattern it also allows us to achieve encapsulation. Lets see the pattern in action.

var myApp = (function () {
    // private fields
    var appName = 'My Awesome App';
    var appVersion = '1.0';
    var container = null;

    // public members
    var appState = 'running';

    // public methods
    function init() {
        // some bootstrapping logic
        container = document.getElementById('container');
        
        // start the application
        run();
    }

    function getAppName() {
        return appName;
    }

    function getAppVersion() {
        return appVersion;
    }
    
    // private methods
    function run() {
        alert('The application has been started!');
    }

    return {
        appState: appState,
        init: init,
        getAppName: getAppName,
        getAppVersion: getAppVersion
    };
})();

myApp.init(); // alerts "The application has been started!"
myApp.getAppName() // returns "My Awesome App"
myApp.getAppVersion() // returns "1.0"
alert(myApp.appState); // alerts "running"
myApp.appName; // returns undefined
myApp.run(); // TypeError: undefined is not a function

As I said earlier thanks to the IIFE we have an isolated scope. We can define variable or even methods that will be visible only inside the IIFE. Once the function is executed it returns an object. That object contains those variables and methods we want to be public. In our case that object is assigned to the myApp variable. This is the only variable that is actually part of the global namespace. Essentially myApp is a module which has certain functionality. This way we can define a complex hierarchy of modules.

Lets list some of the benefits of using the revealing module pattern.

  • Suitable for building singleton classes
  • It keeps the global namespace clean
  • We can achieve encapsulation
  • Give us the ability to define a complex hierarchy of modules
  • It does not rely on the prototype object so the implementation of the public methods cannot be changed accidentally.

When is the revealing module pattern not the best choice?

  • It is best to use it as a singleton class or to define namespaces (modules) so it is not the best choice in every situation
  • We can tweak the code above so that we can have multiple instances of the class. However, that is not the best idea simply because we are not using the prototype so the memory footprint will be big. Each method and variable will be copied with each instance of the class

Revealing Prototype Pattern

This is the most awesome pattern that I’m presenting in this post! The Revealing Prototype Pattern combines the Prototype and Revealing Module patterns into one. We use the prototype for defining the different methods of the class. All methods’ definitions are stored into one place in memory for all instances – low memory footprint. Thanks to the IIFE we can achieve encapsulation the same way we did it using the Revealing Module Pattern. Lets see the Revealing Prototype Pattern in action.

function Person(name) {
    // lets define some public properties
    this.name = name;

    // the class constructor    
}

Person.prototype = (function() {
    // private field
    var energy = 100;

    // public methods
    function eat(foodEnergy) {
        energy += foodEnergy;
        alert('I just ate!');
    }

    function talk() {
        energy -= 1;
        alert('Hello');
    }

    function run() {
        energy -= 10;
        alert('Running!');
    }

    // private methods
    function simplePrivateMethods() {
        alert('I am a private method!');
    }

    return {
        eat: eat,
        talk: talk,
        run: run
    };
})();

var person1 = new Person('Stefan');
var person2 = new Person('John Doe');

person1.run(); // alerts 'Running!'
person1.eat(3); // alerts 'I just ate!'
person1.talk(); // alerts 'Hello'
alert(person1.name); // alerts 'Stefan'
person1.energy; // returns undefined
person1.simplePrivateMethods(); // TypeError: undefined is not a function

I guess that’s all I had to say about these 3 awesome patterns. They are quite useful and great if you want to clean your client-side code. If you liked the article or think that there is something not really right, leave a comment below.

Read more

Recaptcha plugin for Symfony 1.4.x

Categories: PHP

Hello everyone,
Recently I had to add Google Recaptcha to a site built with Symfony 1.4.x. I couldn’t find a 3rd party plugin for that so I built my own. I’ve decided to share my implementation to the whole world. Prior to using the plugin you need to create a Google Recaptcha account.

1. The widget

The widget has a couple of options you can specify. You must specify a public_key. You can get one from your Google Recaptcha account. You can also specify a theme. If omitted the default one will be used. You can find a list of available themes here.

lib/widget/sfWidgetFormGoogleRecaptcha.class

<?php

/**
 * Simple widget based on the Google Recaptcha library
 *
 * @author Stef
 */
class sfWidgetFormGoogleRecaptcha extends sfWidgetForm
{
  public function configure($options = array(), $attributes = array())
  {
    $this->addOption('public_key');
    $this->addOption('theme', null);
  }

  public function render($name, $value = null, $attributes = array(), $errors = array())
  {
    require_once(sfConfig::get('sf_lib_dir') . '/recaptcha/recaptchalib.php');
    $output = '';
    if ($this->getOption('theme')) {
      $output .= '<script type="text/javascript">
                  var RecaptchaOptions = {
                     theme : "' . $this->getOption('theme') . '"
                  };
                  </script>';
    }
    $output .= recaptcha_get_html($this->getOption('public_key'));
    return $output;
  }
}

2. The validator

After submitting a form you need to validate the past security code. The Google Recaptcha validator will handle that. You need to specify a private_key for the validator to work. You can obtain one from you Google Recaptcha account.

lib/validator/sfWidgetFormGoogleRecaptcha.class

<?php

/**
 * Recaptcha validator based on the Google Recaptcha library
 *
 * @author Stef
 */
class sfValidatorGoogleRecaptcha extends sfValidatorBase
{
  public function configure($options = array(), $messages = array())
  {
    $this->addOption('private_key');
  }

  public function doClean($value)
  {
    require_once(sfConfig::get('sf_lib_dir') . '/recaptcha/recaptchalib.php');
    $response = recaptcha_check_answer(
            $this->getOption('private_key'),
            $_SERVER["REMOTE_ADDR"],
            $_POST["recaptcha_challenge_field"],
            $_POST["recaptcha_response_field"]);
    if (!$response->is_valid) {
      throw new sfValidatorError($this, 'invalid');
    }
    return $value;
  }

  public function isEmpty($value) {
    return false;
  }
}

Here is an example code demonstrating how to use the plugin.

// The most awesome Google Recaptcha Widget!!!
$this->widgetSchema['secret'] = new sfWidgetFormGoogleRecaptcha(array(
        'public_key' => 'MY_PUBLIC_KEY',
        'theme' => 'clean'));

// The most awesome Google Recaptcha Validator!!!
$this->validatorSchema['secret'] = new sfValidatorGoogleRecaptcha(array(
        'private_key' => 'MY_PRIVATE_KEY'
    ), array(
        'invalid' => 'The verification code is incorrect.'
    ));
Read more

Stefan Staynov
Stefan Staynov

I'm a web developer with a passion for innovations. Most of the time I code for the web and mobile. I like spending time with my loved ones, playing basketball and sleeping

Categories