An introduction to ES6 features like:
– let vs var vs const
– function
– template string
– enhanced object
– destructuring
– classes
– modules
– promises
– symbols
– Map, Set, WeakMap, WeakSet
– metaprogramming
by Ecma International in ECMA-262 and ISO/IEC 16262. It was created to standardize JavaScript, so as to foster multiple independent implementations. JavaScript has remained the best-known implementation of ECMAScript since the standard was first published, with other well-known implementations including JScript and ActionScript. Coders commonly use ECMAScript for client-side scripting on the World Wide Web, and it is increasingly being used for writing server applications and services using Node.js. AN INTRODUCTION TO ES6 FEATURES 3
default. • If you think that current variable might be re-assigned in the future use let instead. • You should forget about var, and in most cases all your var keywords could be replaced with let straight away! AN INTRODUCTION TO ES6 FEATURES 14
function doSomething(condition) { var color; if (condition) { color = 'blue'; // other code } else { // color exist here with value of undefined } // color exist here with value of undefined } function doSomething(condition) { if (condition) { var color = 'blue'; // other code } else { // color exist here with value of undefined } // color exist here with value of undefined } AN INTRODUCTION TO ES6 FEATURES 15 console.log(value); // Uncaught ReferenceError: value is not defined
console.log(typeof abc); // Uncaught ReferenceError: abc is not defined let abc = 'test'; console.log(typeof abc); // string } console.log(typeof abc); // number console.log(typeof value); // undefined console.log(typeof myConst); // undefined if(true) { console.log(typeof value); // Uncaught ReferenceError: value is not defined console.log(typeof myConst); // Uncaught ReferenceError: myConst is not defined let value = 'test'; const myConst = 10; console.log(typeof value); // string console.log(typeof myConst); // number } AN INTRODUCTION TO ES6 FEATURES 16
mode function mixArgs(first, second) { 'use strict'; first === arguments[0]; second === arguments[1]; first = 'a'; second = 'c'; first !== arguments[0]; second !== arguments[1]; } ES5 non-strict mode function mixArgs(first, second) { first === arguments[0]; second === arguments[1]; first = 'a'; second = 'c'; first === arguments[0]; second === arguments[1]; } ES6 function mixArgs(first, second = "b") { first === arguments[0]; second !== arguments[1]; first = 'a'; second = 'c'; first !== arguments[0]; second !== arguments[1]; } AN INTRODUCTION TO ES6 FEATURES 23
checkArgs(...args) { args.length === 2; args.length === arguments.length; args[0] === arguments[0]; args[1] === arguments[1]; } checkArgs("a", "b"); function f(x, ...y) { // y is an Array return x * y.length; } f(3, "hello", true) === 6 f.length === 1; Restrictions // Rest parameter must be last formal parameter function checkArgs(first, ...args, last) { } // Setter function argument must not be a rest parameter const obj = { set name(...value) { } } AN INTRODUCTION TO ES6 FEATURES 24
is a simple string'; var other = "this is an other string"; // ES6 var str = `this is a simple string`; Multiple string // ES5 var str = 'In ES5 this is not legal'; // Uncaught SyntaxError: Invalid or unexpected token // ES6 var str = `In ES6 this is legal`; String interpolation // ES5 var name = 'Stefano', time = 'today'; var str = 'Hello ' + name + ', how are you ' + time + '?'; // ES6 var name = 'Stefano', age = 20; var str = `Hello ${name}, I’m ${age + 14}?`; AN INTRODUCTION TO ES6 FEATURES 27
{ a: 1, b: 2, c: 3 }; // ES 5 var a = obj.a; var b = obj.b; var c = obj.c; // ES 6 const { a, b, c } = obj; Array matching and fail-soft // ES 5 var list = [ 1, 2, 3 ]; var a = list[0], b = list[2]; var tmp = a; a = b; b = tmp; // ES 6 const list = [ 1, 2, 3 ]; let [ a, , b ] = list; [ b, a ] = [ a, b ]; Deep matching and assigning to different local variable var obj = getObject(); // { type: 'human', person: { name: 'Jonh' }}; // ES 5 var a = obj.type; var b = obj.person.name; // ES 6 let { type: a, person: { name: b } } = obj; Default parameter and properties order function r({ x, y, w = 10, h = 10 }) { return x + y + w + h; } r({ y:2, x:1 }) === 23 AN INTRODUCTION TO ES6 FEATURES 31
= width this._height = height } set width (width) { this._width = width } get width () { return this._width } set height (height) { this._height = height } get height () { return this._height } get area () { return this._width * this._height } } var r = new Rectangle(50, 20); r.area === 1000; ES5 var Rectangle = function (width, height) { this._width = width; this._height = height; }; Rectangle.prototype = { set width (width) { this._width = width; }, get width () { return this._width; }, set height (height) { this._height = height; }, get height () { return this._height; }, get area () { return this._width * this._height; } }; var r = new Rectangle(50, 20); r.area === 1000; Getter/Setter also directly within classes (and not just within object initializers, as it is possible since ECMAScript 5.1). AN INTRODUCTION TO ES6 FEATURES 37
mode, and there’s no way to opt-out of strict mode. • Variables created in the top level of a module aren’t automatically added to the shared global scope. They exist only within the top-level scope of the module. • The value of this in the top level of a module is undefined. • Modules may import bindings from other modules. AN INTRODUCTION TO ES6 FEATURES 43
=> { return x + y }; export const pi = 3.141593; // someApp.js import * as math from "lib/math"; console.log(`2π = ${math.sum(math.pi, math.pi)}`); // otherApp.js import { sum, pi } from "lib/math"; console.log(`2π = ${sum(pi, pi)}`); ES5 // lib/math.js LibMath = {}; LibMath.sum = function (x, y) { return x + y }; LibMath.pi = 3.141593; // someApp.js var math = LibMath; console.log("2π = " + math.sum(math.pi, math.pi)); // otherApp.js var sum = LibMath.sum, pi = LibMath.pi; console.log("2π = " + sum(pi, pi)); AN INTRODUCTION TO ES6 FEATURES 44
export const e = 2.71828182846; export default (x) => Math.exp(x); // someApp.js import exp, { pi, e } from "lib/mathplusplus"; console.log(`e^{π} = ${exp(pi)}`); ES5 // lib/mathplusplus.js LibMathPP = {}; for (symbol in LibMath){ if (LibMath.hasOwnProperty(symbol)) LibMathPP[symbol] = LibMath[symbol]; } LibMathPP.e = 2.71828182846; LibMathPP.exp = function (x) { return Math.exp(x) }; // someApp.js var exp = LibMathPP.exp; var pi = LibMathPP.pi; var e = LibMathPP.e; console.log("e^{π} = " + exp(pi)); AN INTRODUCTION TO ES6 FEATURES 45
requires, they are loaded and processed one by one. Node.js require vs. ES6 import/export • You can have dynamic loading where the loaded module name isn't predefined /static, or where you conditionally load a module only if it's "truly required" (depending on certain code flow). AN INTRODUCTION TO ES6 FEATURES 46 require() from NodeJS (CommonJS) • Import can be asynchronous (and in current ES6 Module Loader, it in fact is) and can perform a little better. • You can use named imports to selectively load only the pieces you need. That can save memory. import from ES6
= Symbol('first name'); typeof firstName === 'symbol'; const person = {}; person[firstName] = 'Stefano'; 'first name' in person === false; person[firstName] === 'Stefano'; firstName.toString() === 'Symbol(first name)'; ES5 // no equivalent in ES5 Symbol is a primitive, unique and immutable data type to be used as an identifier for object properties. The Symbol function also accepts an optional argument that is the description of the symbol. The description itself cannot be used to access the property, but is used for debugging purposes. AN INTRODUCTION TO ES6 FEATURES 52
by the Arraytype, for most of its history (though some may argue all non-array objects are just collections of key-value pairs, their intended use was, originally quite different from arrays). Arrays are used in JavaScript just like arrays in other languages, but the lack of other collection options meant arrays were often used as queues and stacks, as well. Since arrays only use numeric indices, developers used non-array objects whenever a non-numeric index was necessary. That technique led to custom implementations of sets and maps using non-array objects. AN INTRODUCTION TO ES6 FEATURES 56
that cannot contain duplicates. You typically don’t access individual items in a set like you would items in an array; instead, it’s much more common to just check a set to see if a value is present. A map is a collection of keys that correspond to specific values. As such, each item in a map stores two pieces of data, and values are retrieved by specifying the key to read from. Maps are frequently used as caches, for storing data to be quickly retrieved later. AN INTRODUCTION TO ES6 FEATURES 57
retrieving a value const value = map.foo; console.log(value); // "bar" Set const set = Object.create(null); set.foo = true; // checking for existence if (set.foo) { // do something } AN INTRODUCTION TO ES6 FEATURES 58
{}; weakSet.add(key); console.log(weakSet.has(key)); // true weakSet.delete(key); console.log(weakSet.has(key)); // false weakSet.add(1); // Uncaught TypeError: Invalid value used in weak set weakSet.add("a"); // Uncaught TypeError: Invalid value used in weak set weakSet.size === undefined; let key1 = {}; const key2 = {}; const weakSetByIterable = new WeakSet([key1, key2]); console.log(weakSetByIterable.has(key1)); // true console.log(weakSetByIterable.has(key2)); // true key1 = null; // the reference to key1 is no longer accessible AN INTRODUCTION TO ES6 FEATURES 62
const handler = { get: (receiver, name) => { console.log(`LOG: access to ${name} property`); return name in receiver ? receiver[name] : new ReferenceError(`"Property ${name} does not exist.`); }, }; const proxy = new Proxy(myObject, handler); proxy.foo === "Welcome, foo"; // LOG: access to foo property proxy.world.toString() === "ReferenceError: \"Property world does not exist." // LOG: access to world property AN INTRODUCTION TO ES6 FEATURES 69