JavaScript: Design Patterns 02 – Object Literal Pattern

Object Literal Pattern

The most basic approach to dealing with the pollution of the global scope
is to use a simple object literal to wrap a custom library.

Script One
var myLibrary = {
name: 'My super duper library',
say: function(){ return `This entire object will be shadowed...`; }
}
Script Two
var myLibrary = 'This is not even a library, it\'s a string. Boy are you hosed!';

NOTE: only applicable when using 'var' to create variables.
When using 'let', JavaScript will throw an error that the variable name has
already been taken. This includes the case where one of the variables was created
using 'var' and the other was created using 'let', JS will still throw an error.

Custom Name-Spaced Pattern

Uses object literal pattern

Although this may protect the variables, functions, and objects within your
custom library, there is still the issue that someone else may use the same
variable name for an object in their script as you used for the name of your
library's object wrapper.

To overcome this issue, it is standard practice to follow a common Java name-spacing
technique, use a registered domain name you own as your namespace.

Domain Namespace
// Build the domain structure using object literals
// checking to make sure those objects do not already exist
var com = com || {};
com.memorytin = com.memorytin || {};
com.memorytin.myLibrary = com.memorytin.myLibrary || {
name: 'My super duper library',
say: function(){ return `This entire object will be shadowed...`; }
};

Note: the above only works if you are using ‘var’ to create the initial
namespace object. If you use ‘let’, the browser will throw an error due to the
fact that you are using ‘com’ on the right side of the assignment operator and
it has not yet been instantiated.

JavaScript: Design Patterns 01 – Issues with Using the Global Scope

Shadowing

Due to the fact that all scripts are dumped into the JavaScript
global scope, all variables, function, and objects are placed
in that scope. As scripts are loaded into the global scope they are loaded in the
order they are located as the HTML is parsed, because 3rd party libraries are
often used, and because scripts are written by humans, there is a high likelihood
that one or more of those scripts will contain one or more items that have
the same name.

If one script loads and is followed by another that has items with identical
identifiers (names), those that exist in the previous script will be shadowed
or overwritten by those found in the following script. This leads to hard to
identify and correct bugs that can waste a lot of development resources.

Script One
// This script is loaded first
var varWithSameName = {
name: 'Tim',
say: function(){ return `This is the first variable with the name: ${this.name}`; }
}

console.log(varWithSameName.say());
// This script is loaded second
// overrides (shadows) the variable with the same name in the first file
var varWithSameName = {
name: 'Freddy',
say: function(){ return `This is the first variable with the name: ${this.name}`; }
}

console.log(varWithSameName.say());
Console Output
This is the first variable with the name: Tim
This is the first variable with the name: Freddy

NOTE: only applicable when using 'var' to create variables.
When using 'let', JavaScript will throw an error that the variable name has
already been taken. This includes the case where one of the variables was created
using 'var' and the other was created using 'let', JS will still throw an error.

Script One
// using 'let' when declaring variables corrects this problem
let willBreakIfShadowed = 'This will break if it is shadowed in another script.';
Script Two
// using 'let' when declaring variables corrects this problem
var willBreakIfShadowed = 'Broken since script one has this variable and used let to define it.';
Console Output
Uncaught SyntaxError: Identifier 'willBreakIfShadowed' has already been declared
at script-2.js:1

JavaScript: Unobtrusive

It all comes down to separation of concerns. When programming, separation of concerns deals with creating clear and concise boundaries between application components that have different responsibilities but work together to carry out a common overarching goal. So it is with the development of web user interfaces using HTML5, CSS3, and JavaScript. Each of these technologies work together to create interactive and beautiful user interfaces within the browser, but they each have very specific jobs that make these interfaces possible.

HTML: structures content in a very semantic (meaningful) and ordered way.

CSS: beautifies HTML by adding visual enhancements such as color, gradients, borders, padding, margin, fonts, animations, and  positioning.

JavaScript: adds behavior to HTML, allowing HTML to respond to DOM events as users interact with the web page within the browser.

Together these three technologies create a very powerful tool set for the modern web developer and web user interface designer. The difficult part for most web developers is not allowing the three, very closely related technologies, to bleed across their boundaries into each other creating tightly coupled code. This tightly coupled code is usually a result of CSS and JavaScript being placed directly in the HTML.

Unobtrusive method to the rescue. Merriam-Webster defines the word unobtrusive as not attracting attention in a way that bothers or annoys. Well, mashed together HTML, CSS, and JavaScript is bothersome and extremely annoying, especially when it comes to maintainability and defect repair. For this reason developers have begun to make sure their web user interfaces are completely separated. This is accomplished by following a few specific rules:

HTML

  1. keeping HTML markup in separate files

CSS

  1. keeping CSS markup in separate files
  2. referencing those files in the ‘head’ element of the HTML files
  3. never use ‘style’ elements in HTML
  4. never use ‘style’ attributes on HTML elements

JavaScript

  1. keeping JavaScript markup in separate files
  2. referencing those files in the ‘head’ element or at the bottom of the ‘body’ element of the HTML files
  3. never use ‘script’ elements to hold JavaScript code in HTML
  4. only use ‘script’ elements to references a JavaScript file
  5. never use HTML element attributes that bind to DOM events such as ‘onclick’ or ‘onmouseenter’

Unobtrusive JS Example:

<!--DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>JavaScript Event Binding</title>
    <script src="jsEventBinding.js"></script>
</head>
<body>
    <div id="click-me">Click Me</div>
</body>
</html>
/**
 * Created by Tim on 9/9/14.
 */

'use strict';

var elem = document.getElementById('click-me'); // a DOM element
elem.onclick = function () {
    // Do something nifty here
};