Skip to content

annette-arrigucci/es6

Repository files navigation

es6

Examples of ECMAScript 6 features

Let

From Mozilla: let allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. This is unlike the var keyword, which defines a variable globally, or locally to an entire function regardless of block scope.

ES5 way:

function varTest() {
  var x = 1;
  if (true) {
    var x = 2;  // same variable!
    console.log(x);  // 2
  }
  console.log(x);  // 2
}

ES6 way:

function letTest() {
  let x = 1;
  if (true) {
    let x = 2;  // different variable
    console.log(x);  // 2
  }
  console.log(x);  // 1
}

Arrow feature

ES5 way:

var numbers = [1, 5, 10, 15];
var numTimesIndex = numbers.map(function(x, i) {
   return x * i;
});

New way with ES6 arrow feature - we can get rid of function and return keywords:

var numTimesIndex = numbers.map((x, i) => x * i);

If we only have one argument, we don't need parentheses around argument list:

var doubles = numbers.map(x => x * 2);

Lexical this

Unlike functions, arrows share the same lexical this as their surrounding code.

ES5 way - since the thisArg parameter (this) is provided to forEach(), it is passed to callback each time it's invoked, for use as its this value. It's confusing:

var maria = {
            _name: "Maria",
            _friends: ["Nancy", "Annette", "John"],
            printFriends: function() {
                this._friends.forEach(function (element) {
                    document.writeln(this._name + " knows " + element + "<br>")
                }, this);
            }
        }
        var maria1 = Object.create(maria);
        maria1.printFriends();

ES6 way - the thisArg parameter can be omitted as arrow functions lexically bind the "this" value:

 var bob = {
            _name: "Bob",
            _friends: ["Nancy", "Annette", "John"],
            printFriends: function() {
            this._friends.forEach(f =>
            document.writeln(this._name + " knows " + f +"<br>"));
            }
        }
        var bob1 = Object.create(bob);
        bob1.printFriends();

Promises

Promises are basically objects which can be in one of 3 states: • pending • fulfilled • rejected

A Promise gets a callback function as a parameter. In turn, the callback function gets two parameters - a fulfill function if the operation succeeds, and a reject function if the operation failed.

ES5 way:

 var request = new XMLHttpRequest();
        //onload and onerror are event handlers
        request.onload = function () {
            var data = JSON.parse(this.responseText);
            //do stuff with data
            document.writeln("Name: " + data.name);
        };

        request.onerror = function () {
            alert('There was a problem with the request');
        }
        request.open('get', 'https://swapi.co/api/people/1/', true);
        request.send();

ES6 way:

function get(url) {
           // Return a new promise.
           return new Promise((resolve, reject) => {
               // Do the usual XHR stuff
               var request = new XMLHttpRequest();
               request.open('GET', url);

               request.onload = () => {
                   if (request.status == 200) {
                       // Resolve the promise with the response text
                       resolve(request.response);
                   }
                   else {
                       // Otherwise reject with the status text
                       reject(Error(request.statusText));
                   }
               };

               // Handle network errors
               request.onerror = () => {
                   reject(Error("Network Error"));
               };

               // Make the request
               request.send();
           });
       }

       get('https://swapi.co/api/people/2/').then((response) => {
           //console.log("Success!", response);
           var data = JSON.parse(response);
           //do stuff with data         
           document.writeln("Name: " + data.name);
       }, (error) => {
           alert('There was a problem with the request: ' + error);
       })

Classes

ES6 doesn’t really change how JavaScript handles its “classes“ to an object-oriented inheritance model. Strictly speaking, JavaScript does not have classes. It still has prototype-based inheritance. ES6 does provide a cleaner syntax to create objects and deal with inheritance.

ES5 way of creating classes:

       function Vehicle(type, color) { 
           this.type = type;
           this.color = color;
       }

       var car = new Vehicle("Honda", "silver");
       

ES6 way of creating classes:

          class Vehicle {
           constructor(type, color) {
               this.type = type;
               this.color = color;
           }

           getColor() {
               return this.color;
           }
       }

       let car = new Vehicle("Honda", "silver");

Class inheritance in ES5 was really complicated, so a lot of developers didn't bother with it. ES6 provides a much easier way to extend a class.

ES5 way of inheritance:

     // Vehicle constructor function
     function Vehicle(type, color) { 
           this.type = type;
           this.color = color;
       }
     // Car constructor function
       // when called with the "new" operator,
       // a new Car object is created

       function Car(maxSpeed, type, color) {
           // the "new" operator sets the reference of "this" to
           // a new object, the new object is then passed to the
           // Vehicle constructor function through the use of call,
           // so the type and color properties can be set
           this._super.call(this, type, color);
           this.maxSpeed = maxSpeed;
       }

       // cars will inherit from a new object
       // which inherits from the parent
       Car.prototype = Object.create(Vehicle.prototype);

       // set the constructor property back to the Car
       // constructor function
       Car.prototype.constructor = Car;

       // "_super" is NOT part of ES5, its a convention
       // defined by the developer
       // set the "_super" to the Vehicle constructor function
       Car.prototype._super = Vehicle;

       // this will exist on the car's prototype object
       Car.prototype.getMaxSpeedFormatted = function() {
           return this.maxSpeed + "km/h";
       }
       // instantiate a new Car object
       var car2 = new Car(200, "Corvette", "red");

       // invoking function on parent prototype
       document.writeln("Car type is " + car2.type +", color is "+ car2.color);

       // invoking function on child prototype
       // output "1 Smith, Bob"
       document.writeln("Car max speed is "+ car2.getMaxSpeedFormatted());

ES6 way of inheritance: Note that in ES6 you must use "super" to call the parent constructor if you are overriding the constructor.

         //ES6
        class Vehicle {
            constructor(type, color) {
                this.type = type;
                this.color = color;
            }

            getColor() {
                return this.color;
            }
        }
        class Car extends Vehicle {
            constructor(type, color, maxSpeed) {
                super(type, color);
                this.maxSpeed = maxSpeed;
            }

            getMaxSpeedFormatted() {
                return this.maxSpeed + "km/h";
            }
        }
        let car1 = new Car("Mazda","blue", 200);
        document.writeln("Car type is " + car1.type + ", color is " + car1.getColor() + "<br>");
        document.writeln("Car max speed is " + car1.getMaxSpeedFormatted());

Modules

JavaScript has had modules for a long time. However, they were implemented via libraries, not built into the language. ES6 is the first time that JavaScript has built-in modules.

In ES5, you had two widely used approaches for modules: CommonJS and AMD.

CommonJS exports specific objects with free variable “exports” and the keyword “require” is used to import the exports of other modules. This approach is server-side-oriented.

//------ main.js ------
var square = require('./lib').square;
var diag = require('./lib').diag;
console.log("Square of 11 is " + square(11)); // 121
console.log("Diagonal of 4 and 3 is " + diag(4, 3)); // 5

//------ lib.js ------
var sqrt = Math.sqrt;
function square(x) {
    return x * x;
}
function diag(x, y) {
    return sqrt(square(x) + square(y));
}
module.exports = {
    sqrt: sqrt,
    square: square,
    diag: diag,
};

Modules are loaded synchronously the JavaScript thread stops until code has been loaded and blocks browser from running anything else until it finishes loading. You need a library like Browserify if you are using the CommonJS syntax in the browser.

With AMD – Asynchronous Module Definition – you load modules asynchronously in the background and you define a callback function to execute once the dependencies are loaded. You need a library like RequireJS to run this.

Note you can't import modules directly from inside a <script> tag.

//------ main.js ------
require(['apps/mathLib'], function (mathLib) {
    alert("Square of 11 is "+ mathLib.square(11));
});
//------ apps/mathLib.js ------
define([], function () {
    return {
        square: function (x) {
            return x * x;
        }
    };
});

Here is the HTML to call the script:

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <meta charset="utf-8" />
     <title></title>
       <script data-main="scripts/main" src="scripts/require.js"></script> 
   </head>
   <body>
   </body>
</html>

In ES 6, the goal was to create format users of both approaches could be happy with.

  • Compact syntax AND direct support for asynchronous loading and configurable module loading

  • Structure can be statically analyzed

  • Support for cyclic dependencies better than CommonJS

  • Standard has two parts – declarative syntax for import/export and programmatic loader API

ES6 way:

//------ main_es6.js ------
import { square, diag } from 'lib_es6';
alert("ES6 way - square of 11 is "+ square(11)); // 121
alert("ES6 way - diagonal of 4 and 3 is "+ diag(4, 3)); // 5

//------ lib_es6.js ------
export const sqrt = Math.sqrt;
export function square(x) {
    return x * x;
}
export function diag(x, y) {
    return sqrt(square(x) + square(y));
}

BUT I didn't find browser support for ES6 modules in Chrome or Firefox as of this writing (Sept 2017).

References: https://babeljs.io/learn-es2015/

https://www.todaysoftmag.com/article/1731/ecmascript-6-why-and-how-to-use-it-today

https://benmccormick.org/2015/09/14/es5-es6-es2016-es-next-whats-going-on-with-javascript-versioning/

https://benmccormick.org/2017/07/10/how-to-follow-the-javascript-roadmap/

http://kangax.github.io/compat-table/es6/

https://benmccormick.org/2015/12/30/es6-patterns-converting-callbacks-to-promises

http://exploringjs.com/es6/ch_modules.html#sec_overview-modules

https://medium.freecodecamp.org/javascript-modules-a-beginner-s-guide-783f7d7a5fcc

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let

https://stackoverflow.com/questions/4269150/what-is-ecmascript

About

Examples of ECMAScript 6 features

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published