Skip to content

Latest commit

 

History

History
203 lines (149 loc) · 5.35 KB

es6_style.md

File metadata and controls

203 lines (149 loc) · 5.35 KB

Proposal - ES6 Features Styleguide and Preferences

Any performance notes are for Node and are likely drawn from the Six-Speed test.

This is primarily concerned with Node projects and may require additional notes for use with Frontend patterns.

The language of this guide

In compliance with RFC2119,

"Must" - Required for compliance

"Should" - Required in most situations, exceptions may exist but should require consideration

"May" - Not required in any way, optional, allowable but may be ignored.

The features

Strict mode

'use strict';

Must use

You probably should of been using this before, but this is required for several features to operate correctly in the current Node LTS

Object.assign()

let foo = Object.assign({}, {bar: true}, {untrue: false});
//foo is now {bar: true, untrue: false}

Should use

This should replace most utility methods or awkward shims from ES5

const

const foo = 'bar';
//foo is now fixed and can not be re-assigned

Should use

Currenty offers no performance benefit but may help catch bugs. Please remember in JS this is only a constant reference, the properties of a constant object can be still be altered.

let

let foo = 'bar';
//foo can be reassigned, but only exists in the current scope

Should use when not able to use 'const'. May not be able to enforce this via linting

var should never be used anymore. Let follows expected scoping rules.

Map and Set

  • Good perf
  • Useful for our codebase?

I'm not sure if we are using any large object literals, but these offer significant performance and a clean API.

Math/Number upgrades

Overview here

Should use

Pretty much just additional features and improvements here. Remember JS is not appropriate for real math.

Template Strings

let foo = `Hello ${user.firstName},
How are you?`;

Should use over string concatenation in most situations, avoid any logic in templated sections.

Template strings are only very slightly slower and much easier to read.

Classes

class myFoo extends Foo{
    constructor() {
        super();
        this.isMyFoo = true;
    }
    doFoo() {
        return true;
    }
}

Should use for Object Oriented sections.

Object literal shorthand

module.exports = {
    doFoo,
    doBar
};
//same as { doFoo: doFoo, doBar: doBar }

Should use when possible

Significantly reduces redundant code, helps enforce good variable naming.

Arrow Functions

this.foo = true;
this.useFoo = ()=>{
    return this.foo;
}

Should use unless you require a new scope.

Parenthesis always required. Brackets required unless using as a comprehension.

let odds = myNumbers.filter( (num) => return num%2 )

May use as a comprehension (a single line anonymous function with an implicit return).

Powerful but implicit return is a very new feature to JS and may confuse some programmers.

Symbols

const mySecretProperty = Symbol('secret');
someOtherFoo[mySecretProperty] = myHiddenFunction;

Should use when appropriate, likely not needed in our codebase (appropriate use is when decorating foreign objects, etc)

Better then using obnoxious property names or underscores to try and hide features, but this pattern is not typical in our code base.

Parameter defaults

    function makeNewFoo(foo, addDate=false){
        //...
    }

Should use, should come after required params

Exception:

Redux's reducer pattern on the frontend breaks this. This is allowable.

Redux aside, this removes silly code and is sufficiently intuitive for most developers. Optional params should always follow required ones.

Destructuring

    const myFoo = [1, 2];
    const [a, b] = myFoo;
    //a = 1, b = 2

May use, be cautious of complexity or magic behavior

Potential for misuse here but compared to the spread operator not terribly dangerous or unwieldy.

Spread

    const myFoo = [1, 2, 3, 4, 5];
    const [a, b, ...rest] = myFoo;
    //a = 1, b = 2, rest = [3, 4, 5]

May use, be cautious of complexity or magic behavior

Very powerful, but can be difficult to understand. No performance gain, so should only prefer in obvious cases.

Rest

    function myLogger(a, b, ...rest) {
        //...
    }

Should use over Arguments.

Arguments is an array-like, and is awkward to work with. Rest is clean and fairly straightforward.

For...of

    const myFoo = 'a string but an array or other iterable is fine too';
    for(letter of myFoo) {
        //...
    }

Should use when appropriate. Should not use on hot paths or large collections (11x slower than most loops)

For of is painfully slow, but handles a lot of awkward cases and is syntactically enjoyable. As long as it's not used on a hot path or large collections the performance hit should not affect us.

Generators

    function* myGenerator() {
        let x = 0;
        while( x < 10) {
            yield x++;
        }
    }

May use when appropriate. Beware of magic.

Generators are a powerful but hard to grasp pattern. They may be very beneficial in some places but need to be used responsibly.