CEOToolSuite Blog

← Back to Blog

CEOToolSuite EcmaScript Style & Conventions

By CEOToolSuite • December 17, 2025

10 years ago I started out on a quest to distill a full comprehension of javascript down to a functional set of conventions. Much of the internet is bogged down with javascript libraries atop other javascript libraries. Many times pages load slowly because of an incorrect management of web technologies. It's easy to overcomplicate frontend and adding frameworks certainly doesn't help. Most frameworks are reinventing the wheel. The ECMAScript standard has everything needed for fast performant sites. If a library is to be used it should be for a specific niche purpose & only if writing a custom solution would take much more time or the library is simply foundational (think bluebird promises before the Promise object was standardized).

To this end below is a set of conventions I've found to be helpful in writing vanilla js sites.

_

The underscore is helpful for simplifying patterns. There's no point in naming a throw away variable.

Namespacing

By using namespacing, variables (effectively) never collide.

window.namespace__subspace = {
    e: {},
    f: {},
    g: {},
};
  • e - Element cache for DOM references
  • f - Functions for utilities and methods
  • g - Globals for constants, state, and configuration

Variable Declarations

Always use var, never use const or let. This is intentional - var has function scope which is more predictable and hoisting behavior is well understood. const and let add complexity with block scoping that rarely provides real benefits in well-structured code.

Async Operations

Always use async/await over promises with .then() chains. The code is more readable and easier to debug:

// note: preferred
var data = await (await fetch(url)).json();

// note: avoid
fetch(url).then(r => r.json()).then(data => {});

Error Handling

Avoid try/catch blocks - let errors surface for debugging. In production, errors should be caught at the top level and logged appropriately. Wrapping every operation in try/catch hides bugs and makes debugging harder.

Naming Conventions

  • double underscore (__) separates namespace parts: namespace__subspace
  • single underscore (_) separates words within names: word_in_phrase
  • never use hyphens in identifiers

DOM Access

Cache DOM elements in the e object rather than querying repeatedly. Use a refresh_elements() function that automatically populates the cache:

Note the qsa, this is a special case and recommendation for the ECMAScript standard:

window.qsa = document.querySelectorAll.bind(document);

More examples can be found in the example utility file @ the end.

namespace__subspace.f.refresh_elements = () => {
    namespace__subspace.e = {};
    for (var _ of qsa('[namespace__subspace]')) {
        var tagname = _.tagName.toLowerCase();
        var handle = _.getAttribute('namespace__subspace').toLowerCase();
        namespace__subspace.e[`${tagname}__${handle}`] = _;
    }
};

^^ refresh_elements is a phrase thus single underscore.

<button namespace__subspace="submit">Submit</button>
namespace__subspace.e.button__submit.addEventListener('click', namespace__subspace.f.namespace__subspace);

Timing & Race Conditions

With a few basic functions code becomes self documenting & timing issues disappear.

namespace__subspace.f.load__style
namespace__subspace.f.load__script
namespace__subspace.f.load__html
namespace__subspace.f.wait_for_self
namespace__subspace.f.wait_for_load
namespace__subspace.f.wait_for_elem

see example file @ the end.

No Frameworks

Vanilla javascript is sufficient, frameworks add technical debt.

  • bundle size overhead
  • learning curve
  • version upgrade maintenance
  • abstraction that hides what's actually happening

Example

ceots__sites.js

In The Wild

fed.js