Code School JavaScript Best Practices Notes

03.13.2015

The Sword of Syntax

Ternary Conditionals

The ternary conditional provides a shortcut over lengthier condition

Logical Assignment I: OR Assignment

The OR operator takes the leftmost “truthy” value, and if none exists, the last “falsy” value.

Logical Assignment II: AND Assignment

The && operator takes the rightmost “truthy” value or the first “falsy” value.

Switch Blocks & Fall-Through

JavaScript has an alternate way of taking action based on actual values, not just Booleans.
‘Break’ will allow us to leave the entire block of code that contains it, in this case, the switch.
Fall-through will tighten up our code if we stack similar cases before their appropriate action.
The ‘default’ case can help us watch for unavailable regiment values and alert the armorer.
A carefully organized switch block can add LEAST common properties first and MOST common, last.

The Pendant of Performance

Loop Optimization

We can use “cached values” to curtail lengthy, repetitive access to the same data.
For better organization, we can place our new control variable inside the first loop parameter.
Stick with for-loops instead of for-in loops when your goal is only to reach every index.

Script Execution

Scripts encountered high in the <head> or <body> tags of an HTML page can have adverse effects.
Scripts that are not essential to immediate loading of the page should be moved as low as possible.
With external files, the HTML5 async attribute will allow the rest of the page to load before the script runs.

Short Performance Tips

Give all common methods that a “class” of objects will use to the constructor’s prototype.
Each new addition to the DOM causes document “reflow”, which can really hinder user experience.
Fragments are invisible containers that hold multiple DOM elements without being a node itself.
Every var keyword adds a look-up for the JavaScript parser that can be avoided with comma extensions.
Anticipate variable needs to avoid the processor burden of creating a new var over and over.
For concatenations over an array’s contents, use the join() method inherited from the Array prototype.

Measuring Performance I: console.time

This timing feature can help determine the code that creates the best experience.
Since timers are created by the label you provide, creative stacking can produce layers of time data.

Measuring Performance II: Speed Averaging

We’ll use our Date object approach to calculate a more accurate performance over many code repetitions.

The Crystal of Caution

Careful Comparisons

The triple-equals comparator compares both type AND contents.
A === ensures comparison reliability in environments where data may have multiple or unknown types.
The instanceof operator helps identify objects. Use this operator to ensure you’re examining precisely the type of object that your code expects.
An object is an “instance” of all of the prototypes from which it inherits properties.

Exception Handling

A syntax error will not make it past the interpreter. It will be marked as invalid Javascript and reported in the JS console.
“run-time error” is the sort we want to catch and control.
Like other languages, Javascript offers a method for identifying and recovering from errors.
JavaScript can throw multiple useful error types that allow a catch block to “handle” errors more gracefully.
Use conditionals and the throw keyword to craft the right exception scenario based on your expectations.
Try-blocks nested within catch-blocks can organize an option sequence, should our first choice not work out.

Stuff that (Sometimes) Sucks

JavaScript’s ‘with’ keyword is somewhat unreliable and often expensive, so it is generally avoided in practice.
The with keyword takes the entire encapsulated environment of the parameter object and use it to build a new “local” scope within its bracketed block … which is kind of processing-expensive.
Nested objects are frequent in JavaScript, and ‘with’ attempts to help coders avoid typing deep access repeatedly.
As before, caching values saves the day by letting us avoid a bunch of typing, as well as being quite clear in indication.
JavaScript’s ‘eval’ keyword may not be evil, but it can affect legibility, an ability to debug, and performance.
Eval might be useful for dynamic code or uncontrollable data, but it’s still treating the string as a program to expensively compile.
Eval is most often misused for just this kind of mapping numbers to objects, but an array is much more efficient.
Chill, bro. Using eval to parse JSON data is often regarded as vulnerable and unsafe, because eval evaluates any script.
JSON.parse, or a parser library that recognizes JSON, helps to avoid both the security and performance issues posed by eval.
Just because we CAN leave curly braces off of single-statement blocks of code, doesn’t mean we should.
Requiring bracket analysis in order to ensure the proper scoping of necessary additional code will ensure your unpopularity.
In the example of conditional blocks, leaving off brackets may produce valid JavaScript and undesired executions!
For better organization, legibility, and error prevention, brackets are a two-character sacrifice that you should be making.

Number Nonsense

JavaScript uses binary floating point values to handle all of its decimal based operations.
First, the toFixed() method will allow you to select the exact amount of decimal places to display.
If dealing with percentages of money, for example, toFixed() can handle hundredths rounding for you.
A combination of toFixed() and parseFloat() will let us use values of exact length in other math operations.
Instead of looking for a floating point number, parseInt() seeks the first available integer at the front of a string.
Since parseInt() will accept octal, hexadecimal, and decimal values, caution is necessary.
When a browser version or user input is not reliable, make sure to let parseInt() what number system you expect.
Using NaN to check if values are actually JS Numbers seems like a good idea, but it will try to kill you.
If unsure about data type, but highly reliant on a Number, use typeof AND isNaN() as a best practice.
If numerical data may show up as a string, parse data before your type check and add additional checks.

The Mail of Modularity

Namespacing Basics

JavaScript files can often create conflicting global elements, overwriting existing, important data.
Though not native to JS, the namespace concept can limit global impact and provide data protection.
Using a mini-environment as a data “container”, we add a layer of protection around important data.
Namespaces reduce global “footprint” while also keeping data grouped around their intended functionality.
Nesting namespaces provide further organization and protection, as well as help keep variable names intuitive.
Our sensitive data is private by closure, and our public properties are accessible through the namespace.

Anonymous Closures

Javascript’s closure feature will allow us to “privatize” properties.
As a first visual step, we’ll wrap the entire set of properties in an anonymous immediately invoked function expression (IIFE).
Now we’ll make desired private properties into local executable code.
Here’s the money: to make some properties public, return an object.
All of the function’s local variables are “bound down” within the scope of the returned namespace object.

Global Imports

Standard global use in a module pattern causes two problems.
#1: When non-local variables are referenced in a module, the entire length of the scope chain is checked.
#2: Lengthy namespaces mean that global variables have unclear scope, leading to code that is tough to manage.
For clearer, faster globals in modules, use imports.
While devs may still need to review code, importing globals creates faster local variables that are (more) clear in source.
Imports are closed up as local variables.
An imported global variable becomes another piece of data, boxed up in the module’s closure.

Augmentation

Modules often need to have additions to their existing properties.
Augmentation provides extra properties for existing modules.
Augmented properties will have access a new private state, if used, but not to the other file’s closed data.
Best practice: group file contents around needed data.
Any cross-file private state build won’t have the level of privacy of a single closure, and often leads to hard-to-manage code.