Javascript

  • ES6+ functional programming

  • graphql server (express) with passport & jwt authentication and authorization

    graphql server (express) with passport & jwt authentication and authorization :
    https://github.com/helabenkhalfallah/graphql-server

  • apollo server + mongo (mongoose) + psql (Sequelize)

    A basic project for apollo server + mongo (mongoose) + psql (Sequelize) :
    https://github.com/helabenkhalfallah/apollo-graphql-server-sqlize

    With apollo server we don't need express or any others configurations, just apollo-server and graphql.
    From mongoose to psql, essentially we must changes : models and graphql resolve.


    For more details on how to use sequelize for queries and CRUD :
    https://github.com/helabenkhalfallah/node-express-mongoose-sqlize

  • node + express + mongo (mongoose) + psql (Sequelize)

    A basic project for node + express + mongo (mongoose) + psql (Sequelize) :
    https://github.com/helabenkhalfallah/node-express-mongoose-sqlize

    Routes : / routes
    dbs configs, connections and models : /db 
    CRUD : find, finOne, findById, add only if not exist, edit only if exist, delete only if exist ...

     

    Sequelize more details and documentation :

    http://docs.sequelizejs.com/manual/installation/getting-started.html

    http://javasampleapproach.com/node-js/sequelize-orm-build-crud-restapis-with-nodejs-express-sequelize-mysql

    https://stackoverflow.com/questions/36906500/avoid-created-at-and-updated-at-being-auto-generated-by-sequelize

  • JS - Training examples

    HArray : es6 array new concepts

    ES6 Array

    HAsynAwait: es6 async await concept

    ES6 AsynAwait

    HPromises: es6 async promise concept

    ES6 Promise

    HClasses: es6 class concept

    ES6 Classes

    HDestructing: es6 descruting

    ES6 Destructing

    HGenerators: es6 generators concept

    ES6 Generators

    HIterables: es6 iterables concept

    ES6 Iterables

    HMaps: es6 map/weakmap/set concept

    ES6 Maps

    HMutability: es6 mutability concept

    ES6 Mutability

    HNumbers: es6 numbers concept

    ES6 Numbers

    HParameters: es6 parameters concept

    ES6 Pure Impure

    HSpread: es6 spread concept

    ES6 Spread

    HString: es6 strings concept

    ES6 String

  • Best practices snippets

    Replacing switch statements or multiple if with Object literals

    Bad way - switch :

    switch(type) {
    case 'coke':
      drink = 'Coke';
      break;
    case 'pepsi':
      drink = 'Pepsi';
      break;
    default:
      drink = 'Unknown drink!';
    }

     

    Bad way - multiple If :

    function getDrink (type) {
      if (type === 'coke') {
        type = 'Coke';
      } else if (type === 'pepsi') {
        type = 'Pepsi';
      } else if (type === 'mountain dew') {
        type = 'Mountain Dew';
      } else if (type === 'lemonade') {
        type = 'Lemonade';
      } else if (type === 'fanta') {
        type = 'Fanta';
      } else {
        // acts as our "default"
        type = 'Unknown drink!';
      }
      return 'You\'ve picked a ' + type;
    }

     

    Better way :

    function getDrink (type) {
      var drinks = {
        'coke': 'Coke',
        'pepsi': 'Pepsi',
        'lemonade': 'Lemonade',
        'default': 'Default item'
      };
      return 'The drink I chose was ' + (drinks[type] || drinks['default']);
    }

     

    Null, Undefined, Empty Checks Shorthand

    This  code :

    let variable1 = "";
    let variable2 = "12";
    if (variable1 !== null && variable1 !== undefined && variable1 !== "") {
      variable2 = variable1;
    }
    console.log({ variable1, variable2 });

     

    Can be replaced simply by :

    let variable1 = "";
    let variable2 = variable1 || "default";
    console.log({ variable1, variable2 });

     

    Clone an Object Using Spread

    let user = {
      first: "chris",
      last: "burgin"
    }
    let userCopy = {...user}; // new object, not by ref

  • JS - Best Practices (let, const and var)

     

    let and const are block scoped.

    Therefore, referencing block-scoped identifiers before they are defined will produce a ReferenceError.

    console.log(x); // ReferenceError: x is not defined
    let x = 'hi';

    // const and let only exist in the blocks they are defined in.
    {
    let a = 1;
    const b = 1;
    }
    console.log(a); // ReferenceError
    console.log(b); // ReferenceError

     

    Use const for all references; avoid using var.
    If you must reassign references, use let instead of var.
    let is block-scoped rather than function-scoped like var.

    Bad :

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

    Good :

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

     
    Read More :

  • Arrow functions

     

    One of the most anticipated new features in the ES6 Javascript standard was the Arrow Function Expression.

    It promises a shorter syntax than it's predecessor the Function Expression.


    Exemple : get length of each string inside an array

    let celebrities = ['Steve Jobs','Albert Einsten','Nicolas Tesla'];     

    //ES5

    const lengthES5 = celebrities.map(function(celebrity) {

      return celebrity.length;

    });

    console.log(lengthES5); //[ 10, 14, 13 ]


    //ES6
    const lengthES6 = celebrities.map(celebrity => {

      return celebrity.length;

    });

    console.log(lengthES6); //[ 10, 14, 13 ]


    //ES6 much better [ 10, 14, 13 ]
    celebrities.map(celebrity => celebrity.length);

     
    Sandbox :

    Arrow Functions lexically bind their context so this actually refers to the originating context :


    /* Function Object Context */
    var sciences = ['Physics','Chemistry','Math'];
    var searchedScience = 'Math';
    console.log(sciences)
    console.log(searchedScience)

    /* ES5 Function Object Context */
    //solution 1
    var self = this;
    this.sciences.forEach(function(science) {
        if(self.searchedScience === science){
              console.log('Founded Science 1: ', science)
        }else{
              console.log('Not Searched Science 1: ', science)
       }
    });

    //solution 2
    this.sciences.forEach(function(science) {
       if(self.searchedScience === science){
           console.log('Founded Science 2: ', science)
       }else{
           console.log('Not Searched Science 2: ', science)
       }
    }, this);

    //solution 3
    this.sciences.forEach(function(science) {
         if(self.searchedScience === science){
           console.log('Founded Science 3: ', science)
         }else{
           console.log('Not Searched Science 3: ', science)
        }
    }.bind(this));

    /* ES6 Function Object Context */
    this.sciences.forEach((science) => {
       if(this.searchedScience === science){
          console.log('ES6 Founded Science: ', science)
       }else{
          console.log('ES6 Not Searched Science: ', science)
      }
    });

  • JS - Best Practices (Importing/Exporting in ES6)

    Importing with ES6 :

    ES6 provides us with various flavors of importing :

    We can import an entire file :

    import 'underscore';


    Named imports :

    import { sumTwo, sumThree } from 'math/addition';

     

    Rename the named imports :

    import {
    sumTwo as addTwoNumbers,
    sumThree as sumThreeNumbers 
    } from 'math/addition';

     

    Import all the things (also called namespace import) :

    import * as util from 'math/addition';

     

    Import a list of values from a module :

    import * as additionUtil from 'math/addition';
    const { sumTwo, sumThree } = additionUtil;

     

    Exporting with ES6 :

    With ES6, we have various flavors of exporting :

    Named Exports :

    export let name = 'David';
    export let age = 25;​​

     

    Exporting a list :

    function sumTwo(a, b) {
        return a + b;
    }

    function sumThree(a, b, c) {
       return a + b + c;
    }

    export { sumTwo, sumThree }; 

     

    Export functions, objects and values (etc.) simply by using the export keyword :

    export function sumTwo(a, b) {
         return a + b;
    }

    export function sumThree(a, b, c) {
        return a + b + c;
    }

     

    Export default bindings :

    function sumTwo(a, b) {
        return a + b;
    }

    function sumThree(a, b, c) {
       return a + b + c;
    }

    let api = {
      sumTwo,
      sumThree
    };


    export default api;

    /* Which is the same as

    export { api as default };

    */

     

    Always use the export default method at the end of the module. It makes it clear what is being exported, and saves time by having to figure out what name a value was exported as.

     

  • JS - Best Practices (String)

     

    Use single quotes '' for strings.

    // bad
    const name = "My String";

    // bad - template literals should contain interpolation or newlines
    let text = `This string contains "double quotes" which don't need to be escaped anymore.`;     

    // good
    const name = 'My String';

     

    .includes( )

    Instead of checking for a return value > -1 to denote string containment, we can simply use .includes() which will return a boolean:

    const string = 'food';
    const substring = 'foo';
    console.log(string.includes(substring)); // true  

     

    .repeat( )

    // String.repeat(numberOfRepetitions)
    'meow'.repeat(3); // 'meowmeowmeow'  

     

  • JS - Best Practices (Destructuring)

     

    Destructuring allows to extract values from arrays and objects (even deeply nested) and store them in variables with a more convenient syntax.

     

    Destructuring Arrays :

    Old :

    var arr = [1, 2, 3, 4];
    var a = arr[0];
    var b = arr[1];
    var c = arr[2];
    var d = arr[3];

    ES6:

    let [a, b, c, d] = [1, 2, 3, 4];   

    console.log(a); // 1
    console.log(b); // 2

     

    Destructuring Objects :

    Old :

    var luke = { occupation: 'jedi', father: 'anakin' };       
    var occupation = luke.occupation; // 'jedi'
    var father = luke.father; // 'anakin'

    ES6:

    let luke = { occupation: 'jedi', father: 'anakin' };
    let {occupation, father} = luke;

    console.log(occupation); // 'jedi'
    console.log(father); // 'anakin'

     
    Read More:
     

  • JS - Best Practices (Shortcut Notations)

     

    Bad :

    var lunch = new Array();
    lunch[0]='Dosa';
    lunch[1]='Roti';
    lunch[2]='Rice';
    lunch[3]='what the heck is this?';

    Good :

    let lunch = [
    'Dosa',
    'Roti',
    'Rice',
    'what the heck is this?'
    ];

     

    Bad :

    if(v){

       var x = v;

    } else {

       var x =10;

    }

    Good :

    let x = v || 10;     

     

    Bad :

    var direction;
    if(x > 100){
    direction = 1;
    } else {
    direction = -1;
    }

    Good :

    let direction = (x > 100) ? 1 : -1;

     

  • JS - Best Practices (Encapsulate conditionals)

     

    Bad :

    if (fsm.state === 'fetching' && isEmpty(listNode)) {
          // ...
    }

    Correct :

    function shouldShowSpinner(fsm, listNode) {
          return fsm.state === 'fetching' && isEmpty(listNode);
    }

    if (shouldShowSpinner(fsmInstance, listNodeInstance)) {  
         // ...
    }

     

  • JS - Best Practices (Side effects)

    Accidentally modifying global variable :

    Bad :

    // Global variable referenced by following function.
    // If we had another function that used this name, now it'd be an array and it could break it.
    let name = 'Ryan McDermott';

    function splitIntoFirstAndLastName() {
        name = name.split(' ');
    }

    splitIntoFirstAndLastName();
    console.log(name); // ['Ryan', 'McDermott'];

    Correct :

    function splitIntoFirstAndLastName(name) {
         return name.split(' ');
    }

    const name = 'Ryan McDermott';
    const newName = splitIntoFirstAndLastName(name);

    console.log(name); // 'Ryan McDermott';
    console.log(newName); // ['Ryan', 'McDermott'];

     

    In JavaScript, primitives are passed by value and objects/arrays are passed by reference :

    Bad :

    //any other function that uses that cart array will be affected by this addition.
    const addItemToCart = (cart, item) => {
          cart.push({ item, date: Date.now() });
    };

    Correct :

    //clone the cart, edit it, and return the clone
    const addItemToCart = (cart, item) => {
         return [...cart, { item, date: Date.now() }];
    };

     

  • JS - Best Practices (Async Code)

     

    Use Promises whenever you can : instead of writing nested callbacks, you can have chainable Promise calls.

    Avoid :

    asyncFunc1((err, result1) => {
      asyncFunc2(result1, (err, result2) => {  
        asyncFunc3(result2, (err, result3) => {   
          console.lor(result3) })
    }) })


    Prefer :

    asyncFuncPromise1()
    .then(asyncFuncPromise2)
    .then(asyncFuncPromise3)
    .then((result) => console.log(result))
    .catch((err) => console.error(err))

     

    You can use async/await also :

    var foo = async (function() {
    var resultA = await (firstAsyncCall());
    var resultB = await (secondAsyncCallUsing(resultA));
    var resultC = await (thirdAsyncCallUsing(resultB));
           return doSomethingWith(resultC);
    });

     

  • JS - Best Practices (Functions)

    Functions should do one thing only on one level of abstraction.
    Functions should either do something (modify) or answer something (query), but not both.

    Avoid long argument list : use a single object parameter and destructuring assignment instead. It also makes handling optional parameters much easier.

    Bad :

    function getRegisteredUsers (fields, include, fromDate, toDate) {
    /* implementation */ }

    getRegisteredUsers(['firstName', 'lastName', 'email'], ['invitedUsers'], '2016-09-26', '2016-12-13')

    Correct :

    function getRegisteredUsers ({ fields, include, fromDate, toDate })
    { /* implementation */ }

    getRegisteredUsers({
    fields: ['firstName', 'lastName', 'email'],
    include: ['invitedUsers'],
    fromDate: '2016-09-26',
    toDate: '2016-12-13'
    })

     

  • JS - Best Practices (Naming convention)

    Class name :

    Class name should be : UpperCamelCase.

    Bad :

    class tagsinputcomponent extends React.Component

    Correct :

    class TagsInputComponent extends React.Component

    Const name :

    Const name should be : ALL_UPPER_CASE.

    Correct :


    GET_USERS_URL http://localhost:4000/users


    GET_PHOTOS_URL http://localhost:4000/photos


    PHOTO_UPLOAD_URL https://api.application.v1/photo/upload


    IS_ADMIN = false

    Variables name :

    Variable name should be : lowerCamelCase.
    Use intention-revealing names to make names searchable.
    When you choose a name think to the future : review, enhance, refactor …
    The code is a story then make your storyline easy to follow.

    Bad :

    let d
    let elapsed
    const ages = arr.map((i)=> i.age)
    x1 fe2 xbqne
    incrementerForMainLoopWhichSpansFromTenToTwenty
    createNewMemberIfAgeOverTwentyOneAndMoonIsFull
    isOverEighteen()
    const yyyymmdstr = moment().format('YYYY/MM/DD');

    Correct :

    let daysSinceModification
    const agesOfUsers = users.map((user) => user.age)
    isLegalAge()

     

    Make meaningful distinctions and don't add extra, unnecessary nouns to the variable names, like its type :

    Bad :

    let nameString                    
    let theUsers

    Correct :

    let name
    let users

     

    Make your variable names easy to pronounce, because for the human mind it takes less effort to process. Don't cause extra mental mapping with your names.

    Explicit is better than implicit :

    Bad :

    incrementerForMainLoopWhichSpansFromTenToTwenty
    let fName, lName
    let cntr

    let full = false
    if (cart.size > 100) {
    full = true
    }

    Correct :

    let firstName, lastName
    let counter
    const MAX_CART_SIZE = 100
    const isFull = cart.size > MAX_CART_SIZE

    Functions name :

    Functions name should be : lowerCamelCase.
    A function name should be a verb or a verb phrase, and it needs to communicate its intent, as well as the order and intent of the arguments.
    Function names should say what they do.
    A long descriptive name is way better than a short, enigmatic name or a long descriptive comment.

    Bad :

    /**

     * Invite a new user with its email address

     * @param {String} user email address

     */

    function inv (user) { /* implementation */ }


    Correct :
    function inviteUser (emailAddress) { /* implementation */ }