Home Designing and Linking JavaScript Files

Unobtrusive JavaScript

Always use unobtrusive JavaScript to keep all JavaScript commands entirely out of your HTML and entirely inside your JavaScript file. The only JavaScript-related change to your HTML file is to link to your .js file using a script tag. No onclick, onchange, onmouseover, etc. handlers should ever be declared in your HTML files.

Here is an example of (bad) obtrusive JavaScript (with the HTML and associated JavaScript function):

<!-- bad (HTML) -->
<button onclick="foo();">Click me!</button>
// bad (JS)
function foo() {
  alert("You clicked the button!");
}

Here is an example of (good) unobtrusive JavaScript (with the HTML and associated JavaScript code):

<!-- good (HTML) -->
<button id="clickme"gt;Click me!</button>
// good (JS)
window.addEventListener("load", function);

function initialize() {
  document.getElementById("clickme").addEventListener("click", foo);
}

function foo() {
  alert("You clicked the button!");
}

use strict

Always write a "use strict"; declaration at the top of your JavaScript file to tell the browser to enable strict syntax checking of your JavaScript code.

The Module Pattern

Wrap Your JS File's Code Into an Anonymous Function

Always use the "module pattern" of wrapping your JavaScript file's code inside an anonymous function that is immediately invoked to get rid of global variables. This is important because if multiple JavaScript files are linked to the same HTML file and they each define global variables of the same name, they will conflict with each other and cause unpredictable behavior.

let x = 3;
let y = 4;

function f() {
  x++;
}
(function() {
  "use strict";

  let x = 3;
  let y = 4;

  function f() {
    x++;
  }
})();

Minimize Global and Module-Global Variables

Avoid global variables as much as possible. If you use the module pattern, your code should declare 0 global variables. Even when using the module pattern, you should try to minimize the number of "module-global" variables that are declared at the outermost scope within your anonymous wrapper function.

// global variables: avoid these at all costs
let globalBad = 123; // bad
let globalBad2 = 456; // bad

(function() {
  "use strict";

  // module-global variables: some are okay, but don't over-use
  let x = 7;
  let y = 8;

  function f() {
    // local variables: these are great!
    let z = 9;
  }
})();

Avoid DOM Objects as Globals

Do not store DOM elements, such as those returned by the document.getElementById or document.querySelectorAll functions, into global or module-global variables. Every time that you need them in a function, call the appropriate "get" function locally.

let inputBox = document.getElementById("passwordbox");

function f1() {
  inputBox.value = "cuttlefish";
}

function f2() {
  inputBox.value = "musk deer";
}
function f1() {
  let inputBox = document.getElementById("passwordbox");
  inputBox.value = "giraffe";
}

function f2() {
  let inputBox = document.getElementById("passwordbox");
  inputBox.value = "horse";
}

// alternative
function f1() {
  document.getElementById("passwordbox").value = "giraffe";
}

function f2() {
  document.getElementById("passwordbox").value = "horse";
}

Other Global Variable Hacks

Some students try other bizarre hacks to basically achieve global variables. For example, you can stuff various variables and values as dynamically-created fields inside global DOM objects such as the document object, or you can store anything into the global localStorage array. In general, such trickery should be avoided, and global DOM objects should not be abused as a way around declaring global variables.

Minimize Code Redundancy

If you repeat the same code two or more times, find a way to remove the redundant code so that it appears only once. For example, place it into a helper function that is called from both places. If the repeated code is nearly but not entirely the same, try making your helper function accept a parameter to represent the differing part.

foo();
x = 10;
y++;
...

foo();
x = 15;
y++;
helper(10);
helper(15);
...

function helper(newX) {
  foo();
  x = newX;
  y++;
}