Overview of ECMAScript 6, the next version of JavaScript

    For starters, educational program and a few facts:
    • ECMAScript is the official JavaScript language standard (the JavaScript word could not be used because the word Java was a trademark of Sun) That is JavaScript is an implementation of the ECMAScript standard.
    • TC39 is a committee that develops the ECMAScript standard and decides to include features in it.
    • ECMAScript standards are many. The most popular of them is ECMA-262.
    • ECMAScript 5 is the latest edition of the ECMA-262 standard (approved in 2009).
    • Previous versions of the ECMA-262 standard were (I don’t mention the very old ones):
      • ECMAScript 3 - supported by most browsers (approved in 1999).
      • ECMAScript 4 - not taken into account too radical changes to the standard. Later in July 2008, in a stripped-down version (but still much richer than ECMAScript 3), it resulted in a new ECMAScript Harmony project.

    • ECMAScript 6 (codename ECMAScript.next) must be approved before the end of 2013 .


    So, what awaits us in the new version of JavaScript?



    Block scope


    The current version of JavaScript has a functional scope. This means that all variables declared using the keyword varwill be visible anywhere in the function (even if they are declared inside the block):

    function f(a) {
       if (a < 0) {
          var i = 3;
       }
      console.log(i); // 3
    }
    f(-1)
    


    In the new version, a keyword will appear letthat allows you to declare variables with block scope:

    function f(a) {
       if (a < 0) {
          let i = 3;
       }
       console.log(i); // ReferenceError: i is not defined
    }
    f(-1)
    


    Default Parameter Values


    In functions, the ability to declare default values ​​for parameters has been added:

    function setLevel(newLevel = 0) {
       ...
    }
    setLevel(); // newLevel = 0
    setLevel(5); // newLevel = 5
    setLevel(undefined); // newLevel = 0
    


    Named Function Parameters


    The functions also added the ability to specify named parameters:

    function foo({ from, to = 10 }) {
       ...
    }
    foo({ from: 1, to: 5 });
    foo({ to: 5, from: 1 });
    foo({ from: 1 });
    


    Named parameters can be combined with regular (positional parameters):

    function foo(positional, { named1, named2 }) {
       ...
    }
    foo(123, { named1: 'abc', named2: 'def' })
    foo(123, { named2: 'def', named1: 'abc' })
    


    Destructuring assignment


    ECMAScript 6 allows destructuring when assigning:

    let { first: f, last: l } = { first: 'Jane', last: 'Doe' };
    console.log(f); // 'Jane'
    console.log(l); // 'Doe'
    


    By the way, in the example from the previous paragraph (Named Parameters), you saw an example of the destructuring of function parameters.

    The default restructuring is refutable (I have no idea how to translate this). Those. if there is no corresponding field in the source object, an error is thrown:

    let { first: f, last: l } = { first: 'Jane' };  // ошибка
    


    If you do not want the error to be generated, then the variable can be declared irrefutable using the suffix?:

    let { first: f, last?: l } = { first: 'Jane' };  // ok
    console.log(l);  // undefined
    


    Or you can give the variable a default value:

    let { first: f, last: l = 'Unknown' } = { first: 'Jane' };  // ok
    console.log(l);  // 'Unknown'
    


    The default value also works if the corresponding field in the source object is undefined:

    let { a: x = 1 } = { a: undefined }
    console.log(x);  // 1
    


    Finally, if you want all variables to be irrefutable, can you put a suffix? at the end of the entire assignment pattern:

    let { foo: f }? = anything;  // всегда ok
    

    In the last example, the variable fwill be initialized with a value undefinedif anythingit is equal undefined, nullor without a field foo.

    Using destructuring, you can change the value of two variables (without any tmp) with one line of code :

    { foo: foo, bar: bar } = { foo: bar, bar: foo};
    


    Or shorter:

    [ foo, bar ] = [ bar, foo ];
    


    Classes


    Classes will appear in ECMAScript 6:

    // Supertype
    class Person {
       constructor(name) {
          this.name = name;
       }
       describe() {
          return "Person called " + this.name;
       }
    }
    // Subtype
    class Employee extends Person {
       constructor(name, title) {
          super.constructor(name);
          this.title = title;
       }
       describe() {
          return super.describe() + " (" + this.title + ")";
       }
    }
    


    Now you can use these classes:

    let jane = new Employee("Jane", "CTO");
    jane instanceof Person; // true
    jane instanceof Employee; // true
    jane.describe(); // 'Person called Jane (CTO)'
    


    All the same, it was possible to achieve using prototypes:

    // Supertype
    function Person(name) {
       this.name = name;
    }
    Person.prototype.describe = function () {
       return "Person called " + this.name;
    };
    // Subtype
    function Employee(name, title) {
       Person.call(this, name);
       this.title = title;
    }
    Employee.prototype = Object.create(Person.prototype);
    Employee.prototype.constructor = Employee;
    Employee.prototype.describe = function () {
       return Person.prototype.describe.call(this) + " (" + this.title + ")";
    };
    


    As you can see, classes in ECMAScript 6 are just syntactic sugar over constructors and functions.

    Classes can have static methods:

    class Point {
       constructor(x, y) {
          this.x = x;
          this.y = y;
       }
       static zero() {
          return new Point(0, 0);
       }
    }
    


    There will be no private fields and methods (at least in ECMAScript 6). However, some data hiding will still appear. Through the modules.

    Modules


    Modules finally appear in JavaScript:

    module Math {
       export function sum(x, y) {
          return x + y;
       }
       export var pi = 3.141593;
       // Не видна снаружи
       function internal() {
          ...
       }
    }
    


    Importing a module:

    import Math.{sum, pi}; 
    alert("2π = " + sum(pi, pi));
    


    You can use *to import everything:

    import Math.*; 
    alert("2π = " + sum(pi, pi));
    


    Modules can be nested in each other:

    module Widgets {
       module Button { ... }
       module Alert { ... }
       module TextArea { ... }
       ...
    }
    import Widgets.Alert.{messageBox, confirmDialog};
    ...
    


    Modules can be downloaded from the web or via the file system:

    module JSON = require('http://json.org/modules/json2.js'); // web
    import JSON.*;
    module File = require('io/File'); // file system
    import require("bar.js").y; // file system
    


    All global variables in modules are global only in this module.

    Cyclic dependencies between modules are possible.

    Cycle for-of


    As you know, a loop for-inin JavaScript iterates over all fields of an object (including inherited ones). Those. iterating over array values ​​is possible, but dangerous:

    let arr = [ "blue", "green" ];
    arr.notAnIndex = 123;
    Array.prototype.protoProp = 456;
    for(var x in arr) {
       console.log(x); // Напечатает blue, green, notAnIndex, protoProp
    }
    


    In ECMAScript 6, a loop will appear for-ofthat will solve this problem:

    for(var x of arr) {
       console.log(x); // Напечатает только blue, green
    }
    


    Also, perhaps, an operator will be added to the language yield, with which you can easily and beautifully write custom iterators.

    Arrow Functions


    In ECMAScript 6, arrow functions will appear:

    let squares = [ 1, 2, 3 ].map(x => x * x);
    


    The code above is equivalent to this:

    let squares = [ 1, 2, 3 ].map(function (x) { return x * x });
    


    Arrow functions are slightly different from ordinary functions. First of all, by the fact that in arrow functions it is thistied to a higher context. Those.

    let jane = {
       name: "Jane",
       sayHello: function (friends) {
          friends.forEach(friend => { console.log(this.name + " says hello to " + friend) });
       }
    }
    jane.sayHello([ 'Mark', 'John' ]);
    

    will output
    Jane says hello to Mark
    Jane says hello to John
    

    as expected. A

    let jane = {
       name: "Jane",
       sayHello: function (friends) {
          friends.forEach(function(friend) { console.log(this.name + " says hello to " + friend) });
       }
    }
    

    will output:
     says hello to Mark
     says hello to John
    


    The problem is that thisof an anonymous function function(friend) { ... })overlaps thisfrom the surrounding context. In order to avoid this, you can use the old trick with var self = thisor use the function bind:

    var jane = {
       name: "Jane",
       sayHello: function (friends) {
          friends.forEach(function (friend) {
             console.log(this.name + " says hello to " + friend)
           }.bind(this));
       }
    }
    


    Those. essentially arrow functions are again syntactic sugar over existing anonymous functions:

    (x, y) => x + y + this.z
    


    there is nothing more than:

    function (x, y) { return x + y + this.z }.bind(this)
    


    Other differences of arrow functions from ordinary functions:
    • You cannot use arrow functions as constructors ( new (() => {})throw an error)
    • Arrow functions cannot access a variable arguments(and no reason)


    Otherwise, arrow functions do not differ from ordinary functions. They support default values, a variable number of parameters, operators typeofand instanceof:

    typeof () => {}; // 'function'
    () => {} instanceof Function; // true
    


    Conclusion


    I have described far from everything that will appear in the new ECMAScript 6 standard. And it is very possible that something from what I wrote above can change or not appear at all in the standard. However, all that I described is not a rumor. These are the things really being discussed by the TC39 committee. And by the end of this (2013) year, the standard should be approved.

    References


    Most of the information was taken from the blog of Dr. Axel Rauschmayer , which I was lucky to listen to and see live at the CodeFest conference in Novosibirsk.

    PS. Thank you 2GIS for organizing the conference!

    Also popular now: