Guide for the daily JavaScripter
Damian Cipolat

Damian Cipolat @damxipo

About: Hi, I'm from Argentina. I specialize in Nodejs and microservice technologies over AWS. Thanks for reading me XD

Location:
Argentina
Joined:
Feb 28, 2020

Guide for the daily JavaScripter

Publish Date: Feb 28 '20
167 7

Guide for the daily JavaScripter

This document is a summary of good programming practices in js in general.

Part of the document is based in Airbnb guideline, and other in profesional experience.

https://github.com/airbnb/javascript

The NODE.JS section is a summary of different readings and my own experience in the tecnology.

Content list

NODE.JS

Paradigm - FP

Javascript is a multiparadigm programming language. While we could make a mix of paradigms in our code is better, focus on just one. The trend today is to focus on functional programming, both to develop a frontend or a backend.

These are some functional programming principles that are useful to know.

  1. Thinks in functions
  2. Lambda
  3. Curry
  4. Stateless
  5. Composing functions
  6. pure functions:
  7. Side effects
  8. Functor
  9. High order functions
  10. First class
  11. Mutations

👉 To continue reading about FP, go to this link:
https://github.com/damiancipolat/Functional_programming_in_JS

⮬ back to top

Naming conventions

How to name objects in js.

Based in the Airbnb guide points: 23.1, 23.2, 23.3, 23.6

  • Avoid single letter names. Be descriptive with your naming.

    // bad
    function q() {
    }
    
    // good
    function query() {
    }
    
  • Use camelCase when naming objects, functions, and instances.

    // bad
    const OBJEcttsssss = {};
    const this_is_my_object = {};
    function c() {}
    
    // good
    const thisIsMyObject = {};
    function thisIsMyFunction() {}
    
  • Use PascalCase only when naming constructors or classes.

    // bad
    function user(options) {
      this.name = options.name;
    }
    
    const bad = new user({
      name: 'nope',
    });
    
    // good
    class User {
      constructor(options) {
        this.name = options.name;
      }
    }
    
    const good = new User({
      name: 'yup',
    });
    
  • Use uppercase only in constants.

    // allowed but does not supply semantic value
    export const apiKey = 'SOMEKEY';
    
    // better in most cases
    export const API_KEY = 'SOMEKEY';
    

⮬ back to top

Semicolons

Based in the Airbnb guide points: 21.1.

Why? When JavaScript encounters a line break without a semicolon, it uses a set of rules called Automatic Semicolon Insertion to determine whether or not it should regard that line break as the end of a statement, and (as the name implies) place a semicolon into your code before the line break if it thinks so. ASI contains a few eccentric behaviors, though, and your code will break if JavaScript misinterprets your line break. These rules will become more complicated as new features become a part of JavaScript. Explicitly terminating your statements and configuring your linter to catch missing semicolons will help prevent you from encountering issues

```javascript
// bad
function foo() {
  return
    'search your feelings, you know it to be foo'
}

// good
const luke = {};
const leia = {};
[luke, leia].forEach((jedi) => {
  jedi.father = 'vader';
});
```

⮬ back to top

Comments

Standarize js comments in your projects. Visualstudio code recognize this format.

Use JSDOC https://jsdoc.app/about-getting-started.html format.

  • Use block comment.

    /** This is a description of the foo function. */
    function foo() {
    }
    
  • Use JSDOC tag to describe a function.

    /**
    * Represents a book.
    * @constructor
    * @param {string} title - The title of the book.
    * @param {string} author - The author of the book.
    */
    function Book(title, author) {
    }
    

⮬ back to top

Promises.

Change the way to handle callbacks.

  • If you work with callback styled function, wrap it in a promise:
  function doAsync(function(err, data) { 
    if (err) {
      // error
    } else {
      // success
    }
  });
  • With Promises:
const doAsyncPomise= () =>{

    return new Promise((resolve,reject)=>{

        if (err)
            reject(err);
        else
            resolve(..);

    });

}

⮬ back to top

Error handling

Different ways of handle errors.

  • Using sync functions:
  try{
      makeSomething();
  } catch(err){
      rollBack();
  }
  • Using a function that return promise:
  makeSomething()
      .then(data=>{
          //....
      })
      .catch(err=>{
          rollback(...)
      });
  • Using into a async/await function:
  const run = async ()=>{

      try{
          const result = await makeSomething();
      } catch(err){
          rollBack(..)
      }

  };
  • Avoid to return "error structures" to comunicate an error, is better to launch an exception.
    //bad
    const run = (param)=>{

      const result = makeSomething(param);

      if (result){
          return result;
      } else {
          return {
              error:'processing error'
          };
      }
  }

  //good
  const run = (param)=>{

    if (!param)
      throw new Error('Bad parameters');

    const result = makeSomething(param);

    if (!result)
      throw new Error('Processing error');

    return result;

  }

⮬ back to top

Comparision

Improve your comparision methods.

Based in the Airbnb guide points: 15.1, 15.2, 15.3, 15.5, 15.6, 15.7

  • Use === and !== over == and !=.
  • Conditional statements such as the if statement evaluate their expression using coercion with the ToBoolean.
    https://github.com/airbnb/javascript/blob/master/README.md#comparison--if

    if ([0] && []) {
      // true
      // an array (even an empty one) is an object, objects will evaluate to true
    }
    
  • User shorcuts for booleans.

    // bad
    if (isValid === true) {
      // ...
    }
    
    // good
    if (isValid) {
      // ...
    }
    
  • Ternaries should not be nested and generally be single line expressions.

    // bad
    const foo = maybe1 > maybe2
      ? "bar"
      : value1 > value2 ? "baz" : null;
    
    // split into 2 separated ternary expressions
    const maybeNull = value1 > value2 ? 'baz' : null;
    
    // better
    const foo = maybe1 > maybe2
      ? 'bar'
      : maybeNull;
    
    // best
    const foo = maybe1 > maybe2 ? 'bar' : maybeNull;
    
  • Ternaries should not be nested and generally be single line expressions.

    // bad
    const foo = a ? a : b;
    const bar = c ? true : false;
    const baz = c ? false : true;
    
    // good
    const foo = a || b;
    const bar = !!c;
    const baz = !c;
    

⮬ back to top

Iterations

Handle the lopps in a functional style.

Based in the Airbnb guide points: 11.1

  • Don’t use iterators, prefer js higher-order functions instead of for / for..in

    // bad
    const increasedByOne = [];
    for (let i = 0; i < numbers.length; i++) {
      increasedByOne.push(numbers[i] + 1);
    }
    
    // good
    const increasedByOne = [];
    numbers.forEach((num) => {
      increasedByOne.push(num + 1);
    });
    

⮬ back to top

Functions

How to handle functions in a modern way.

Based in the Airbnb guide points: 7.1, 7.5, 7.6, 7.7, 7.10, 7.12, 7.13

  • Use named arrow function expressions instead of function declarations.

    // bad
    function foo() {
      // ...
    }
    
    // bad
    const foo = () => {
      // ...
    };
    
  • Never name a parameter arguments..

        // bad
        function foo(name, options, arguments) {
          // ...
        }
    
        // good
        function foo(name, options, args) {
          // ...
        }
    ``
    - Never use arguments, opt to use rest syntax ... instead. 
    


    javascript
    // bad
    function concatenateAll() {
    const args = Array.prototype.slice.call(arguments);
    return args.join('');
    }

    // good
    function concatenateAll(...args) {
    return args.join('');
    }
    ``

  • Avoid side effects with default parameters..
    `javascript
    const b = 1;
    // bad
    function count(a = b++) {
    console.log(a);
    }
    count(); // 1
    count(); // 2
    count(3); // 3
    count(); // 3

    • Never mutate parameters. `javascript // bad function f1(obj) { obj.key = 1; }

    // good
    function f2(obj) {
    const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1;
    ``

⮬ back to top

String

Best way to handle strings.

Based in the Airbnb guide points: 6.1, 6.2, 6.3, 6.4

  • Use single quotes '' for strings, don't mix with "".

    // bad
    const name = "Bart";
    
    // bad - template literals should contain interpolation or newlines
    const name = `Marge`;
    
    // good
    const name = 'Homer';
    
  • Use template string instead of concatenate string with values.

    const name    = 'Bart';
    const surname = 'Simpson';
    
     // bad
    const txt = 'hello mr. '+name+',  '+surname';
    
    // good
    const txt = `hello mr. ${name},  ${surname}`;
    ``
    **[⮬ back to top](#table-of-contents)**
    

Destructuring

Destructuring simply implies breaking down a complex structure into simpler parts.

Based in the Airbnb guide points: 5.1, 5.2, 5.3

  • Use destructuring when accessing and using multiple properties of an object.

    
    javascript
    // bad
    function getFullName(user) {
      const firstName = user.firstName;
      const lastName = user.lastName;
    
      return `${firstName} ${lastName}`;
    }
    
    // good
    function getFullName(user) {
      const { firstName, lastName } = user;
      return `${firstName} ${lastName}`;
    }
    
    
    
  • Use array destructuring.

    
    javascript
    // bad
    const first = arr[0];
    const second = arr[1];
    
    // good
    const [first, second] = arr;
    ``
    **[⮬ back to top](#table-of-contents)**
    

Arrays

Array manipulation practices.

Based in the Airbnb guide points: 4.1, 4.3, 4.4, 4.7

  • Is important to know this array prototypes: map, reduce, forEach, filter, find, push, pop, slice. https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Array/prototype
  • Use the literal syntax for array creation.

    `javascript
    // bad
    const items = new Array();

    // good
    const items = [];
    `

    • Use array spreads ... to copy arrays: `javascript // bad const len = items.length; const itemsCopy = []; let i;

    for (i = 0; i < len; i += 1) {
    itemsCopy[i] = items[i];
    }

    // good
    const itemsCopy = [...items];
    `

    • To convert an iterable object to an array, use spreads ... instead of Array.from. `javascript // bad const items = new Array();

    // good
    const items = [];
    `

    • Use array spreads ... to copy arrays: `javascript // bad const len = items.length; const itemsCopy = []; let i;

    for (i = 0; i < len; i += 1) {
    itemsCopy[i] = items[i];
    }

    // good
    const itemsCopy = [...items];
    `

    • Use return statements in array method callbacks: `javascript // bad inbox.filter((msg) => { const { subject, author } = msg; if (subject === 'Mockingbird') { return author === 'Harper Lee'; } else { return false; } });

    // good
    inbox.filter((msg) => {
    const { subject, author } = msg;
    if (subject === 'Mockingbird') {
    return author === 'Harper Lee';
    }

    return false;
    });
    `

⮬ back to top

Objects

Some tips of how to improve the object manipulation.

Based in the Airbnb guide points: 3.1,3.3,3.4,3.6,3.8

  • Use the literal syntax for object creation.
    `javascript
    // bad
    const item = new Object();

    // good
    const item = {};
    `

  • Use object method shorthand.
    `javascript
    // bad
    const atom = {
    value: 1,

    addValue: function (value) {
    return atom.value + value;
    },
    };

    // good
    const atom = {
    value: 1,

    addValue(value) {
    return atom.value + value;
    },
    };
    `

  • Use property value shorthand.
    `javascript
    const bart = 'Bart Simpson';

    // bad
    const obj = {
    bart: bart,
    };

    // good
    const obj = {
    bart,
    };
    `

  • Only quote properties that are invalid identifiers in the example is 'bla-bla'.
    `javascript
    // bad
    const bad = {
    'foo': 3,
    'bar': 4,
    'data-blah': 5,
    };

    // good
    const good = {
    foo: 3,
    bar: 4,
    'bla-bla': 5,
    };
    `

  • If you need to access dinamycali to one object atributte:
    `javascript
    const person = {
    name:'Damian',
    age:32
    };

    const key = 'age';
    console.log(person[key]);
    `

  • Prefer the object spread operator over Object.assign to shallow-copy objects:
    `javascript
    // bad
    const original = { a: 1, b: 2 };
    const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 }

    // good
    const original = { a: 1, b: 2 };
    const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }
    `

⮬ back to top

Properties

Based in the Airbnb guide points: 12.1, 12.2

  • Use dot notation when accessing properties.

    `javascript
    const luke = {
    jedi: true,
    age: 28,
    };

    // bad
    const isJedi = luke['jedi'];

    // good
    const isJedi = luke.jedi;
    `

    • Use bracket notation [] when accessing properties with a variable: `javascript const person = { name:'Damian', age:32 };

    const key = 'age';
    console.log(person[key]);
    `

⮬ back to top

Primitives

The basic type data provided in js.

Based in the Airbnb guide points: 1.1

When you access a primitive type you work directly on its value.

  • string
  • number
  • boolean
  • null
  • undefined
  • symbol

⮬ back to top

Variables

Some points of how to handle and declare variables in javascript.

Based in the Airbnb guide points: 2.1, 2.2, 13.1, 13.2, 13.3, 13.4, 13.5, 13.8

  • Avoid to use global variable in the projects.
  • Avoid use var in variable declaration, use const.
  • If you must reassign references, use let instead of const.
  • Group all your const and then group all your let.
  • Remove unused variables.

    `javascript
    // bad
    var a = 1;
    var b = 2;

    // good
    const a = 1;
    const b = 2;

    // bad
    var count = 1;
    if (true) {
    count += 1;
    }

    // good, use the let.
    let count = 1;
    if (true) {
    count += 1;
    }

    // bad
    superPower = new SuperPower();

    // good
    const superPower = new SuperPower();
    `

⮬ back to top

TL;DR;

Don't use:

  • No global vars.
  • Declare variables using "var".
  • Declare functions using "function" keyword.
  • Avoid use "for" in loops.
  • Array push, inmutability.
  • Class.
  • Use delete to remove a object atribute.
  • Avoid nested if.
  • else if.
  • Heavy nesting https://www.w3.org/wiki/JavaScript_best_practices#Avoid_heavy_nesting.
  • Avoid to add prototype to functions that could be used in a module.

Use:

  • Common code in functions, follow D.R.Y principle.
  • Shorcut notation.
  • Spread operator over Object.assign (airbnb 3.8).
  • Pascal case naming.
  • Modularize your code in modules.
  • const and let!.
  • Literal syntax for object creation (airbnb 3.1).
  • Computed property names when creating objects (airbnb 3.2).
  • Property value shorthand (airbnb 3.4).
  • Group your shorthand properties at the beginning of your objec (airbnb 3.5).
  • use the literal syntax for array creation (airnbnb 4.1).
  • Use array spreads ... to copy arrays. (airbnb 4.3).
  • use spreads ... instead of, Array.from. (airbnb 4.4).
  • Use return statements in array method callbacks (airbnb 4.7).

⮬ back to top

NPM:

Some interesting tips and commands to use in npm.

#### npm init
Execute this command whenever you start a project from scratch

#### npm install {dependency} --save
Execute this command using the save parameter, when you need to install a new module, the save parameter record the dependecy in the package.json

#### npm install {dependency} --save--dev
Install a new dependency but only for development purposes, example unit testing.

#### npm install
Will install both "dependencies" and "devDependencies" from package.json.

#### npm install --dev
Run this command when you need to install only dev dependencys example into a ci/cd step to run test. Will only install "devDependencies" from package.json

#### npm install --production
Will only install "dependencies" from package.json.

#### npm audit
This command list all the security vulnerabilities of the dependencys installed in the package.json

#### npm audit --fix
Subcommand to automatically install compatible updates to vulnerable dependencies.

⮬ back to top

Package.json:

  • VERSION:

Use the version attribute to save the current project version follow the SEMVER rules, http://semver.org

`json
{
"name": "api",
"version": "1.0.0",
"description": "orders api",
"main": ""
}
`

SEMVER rules:
MAJOR: version when you make incompatible API changes.
MINOR: version when you add functionality in a backwards-compatible manner.
PATCH: version when you make backwards-compatible bug fixes.

  • DEPENDENCIES:

Make sure you are saving the dependencies modules in the "devDependencies" section.

  • SCRIPTS:

Its important to complete the script section of the package.json, the basic script should be:

`sh
npm start
npm test
npm deploy
`

⮬ back to top

Recommendations:

  • Use npm mayor / npm minor things change the versions.
  • Set NODENV in production.
  • Split common code in modules.
  • Don't use sync function for i/o;
  • Use streams.
  • Communicate error using exceptions.
  • Try/catch if you can solve the exception.
  • Good use of promises.
  • Promise.all to paralellize always
  • Wrap promise.all to avoid partial executions.
  • Async / await instead of promise.then
  • Don't use callbacksm replace them by Promise.
  • Avoid heavy nesting.
  • Avoid use else if.
  • Avoid nested if.
  • Avoid use global variables.
  • Don't abuse installing modules
  • Think first in use node core modules instead of search npm modules.
  • Create a logger wrapper instead of use console.log, (winston)
  • Create private npm modules for general purposes code used in different projects. Reutilizations.
  • Avoid the "core" patterns', the idea is avoid putting the entire business code of the application in a set of npm modules
  • Don't use class is better to focus in modules that export functions.
  • Externalize your config, make easy the test later.

Stacks:
Some recomendatios of modules.

  • For testing: Jest or Mocha / Chai / Proxyquire.
  • For logging: Winston.
  • For Api: Expressjs, Hapijs, Restify.
  • For SQL: Sequlize.
  • For Mongodb: Mongoose.
  • For Serverless: Serverless framework or AWS-CDK https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html
  • For request: node-fetch or axios.
  • For time: moment / moment-timezone.
  • For lint: es-lint.
  • For schema validation: Joi

⮬ back to top

Have fun! 🛸🐧🐲👽👆👻👺

Comments 7 total

  • Jan Küster 🔥
    Jan Küster 🔥Feb 28, 2020

    Thank you for this summary. I would like to read more on the functional paradigm but the link is broken in

    👉 To continue reading about FP, go to this document.

    would you mind checking and updating it?

  • Carlos Trapet
    Carlos TrapetFeb 28, 2020

    This is generally a good compilation, but a beginner would totally get lost in the amount of concepts, especially considering you don't explain what they are/what they mean. Consider providing links for them.

    Also:

    Async / await instead of promise.then

    Why?? Is this based on any arguments or is it just something made up out of the blue?

    I must strongly disagree, the only advantage async/await has over Promise chaining is that with async/await you can directly assign the value the promise resolves to, saving you a whopping line of code.

    I personally prefer promise chaining as I find it much more flexible; maybe you don't want to pause code execution after all.

    • Damian Cipolat
      Damian CipolatFeb 28, 2020

      Thanks for the comment, for this documment I assume the developer has some of experience working in node.js the main idea is not a tutorial style. Is more a summary of best practices and code-style.

    • Matei Adriel
      Matei AdrielFeb 29, 2020

      Wdym by pause code execution? Async await doesnt actually pause it everywhere, just in the function you call it from.

  • thedevkim
    thedevkimFeb 29, 2020

    Thank youu! this will really help building up clean code.

  • Ozgur Yasin Aydin
    Ozgur Yasin AydinMar 10, 2020

    Very nice summary.

    Btw I think instead of "Comparision" you meant "Comparison"?

    Also, my DNS servers (Cloudflare & Google) can't resolve your website's domain, damiancipolat.com or www.damiancipolat.com .

    3- Markdown seems to be broken after concatenateAll part.

Add comment