ES6
Getting Started
Block-scoped {.row-span-2}
Let
function fn () { let x = 0 if (true) { let x = 1 // only inside this `if` }}Const
const a = 1;let is the new var. Constants (const) work just like let, but cannot be reassigned. See:
Let and const
Template Strings {.row-span-2}
Interpolation
const message = `Hello ${name}`;Multi-line string
const str = `hellothe world`;Templates and multiline strings. See: template strings
Binary and octal literals
let bin = 0b1010010;let oct = 0o755;See: Binary and Octal Literals
Exponential Operator
const byte = 2 ** 8;Same as: Math.pow(2, 8)
New library additions
New string methods
"hello".repeat(3);"hello".includes("ll");"hello".startsWith("he");"hello".padStart(8); // "hello""hello".padEnd(8); // "hello""hello".padEnd(8, "!"); // hello!!!"\u1E9B\u0323".normalize("NFC");New Number Methods
Number.EPSILON;Number.isInteger(Infinity); // falseNumber.isNaN("NaN"); // falseNew Math methods
Math.acosh(3); // 1.762747174039086Math.hypot(3, 4); // 5Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2); // 2New Array methods
//return a real arrayArray.from(document.querySelectorAll("*"));//similar to new Array(...), but without the special single-argument behaviorArray.of(1, 2, 3);kind
class Circle extends Shape {Constructor
constructor (radius) { this.radius = radius}method
getArea () { return Math.PI *2 *this.radius}Call the superclass method
expand(n) { return super.expand(n) *Math.PI}Static methods
static createFromDiameter(diameter) { return new Circle(diameter /2)}Syntactic sugar for prototypes. See: classes
Private class
The javascript default field is public (public), if you need to indicate private, you can use (#)
class Dog { #name; constructor(name) { this.#name = name; } printName() { // Only private fields can be called inside the class console.log(`Your name is ${this.#name}`); }}
const dog = new Dog("putty");//console.log(this.#name)//Private identifiers are not allowed outside class bodies.dog.printName();Static private class
class ClassWithPrivate { static #privateStaticField; static #privateStaticFieldWithInitializer = 42;
static #privateStaticMethod() { // … }}Promises
make the commitment
new Promise((resolve, reject) => { if (ok) { resolve(result); } else { reject(error); }});for asynchronous programming. See: Promises
Using Promises
promise .then((result) => { ··· }) .catch((error) => { ··· })Using Promises in finally
promise .then((result) => { ··· }) .catch((error) => { ··· }) .finally(() => { /*logic independent of success/error */ })The handler is called when the promise is fulfilled or rejected
Promise function
Promise.all(···)Promise.race(···)Promise.reject(···)Promise.resolve(···)Async-await
async function run () { const user = await getUser() const tweets = await getTweets(user) return [user, tweets]}async functions are another way to use functions. See:
Async Function
Destructuring
Destructuring assignment
Arrays
const [first, last] = ["Nikola", "Tesla"];Objects
let { title, author } = { title: "The Silkworm", author: "R. Galbraith",};Supports matching arrays and objects. See: Destructuring
Defaults
const scores = [22, 33];const [math = 50, sci = 50, arts = 50] = scores;//Result://math === 22, sci === 33, arts === 50A default value can be assigned when destructuring an array or object
Function parameters
function greet({ name, greeting }) { console.log(`${greeting}, ${name}!`);}greet({ name: "Larry", greeting: "Ahoy" });Destructuring of objects and arrays can also be done in function parameters
Defaults
function greet({ name = "Rauno" } = {}) { console.log(`Hi ${name}!`);}greet(); // Hi Rauno!greet({ name: "Larry" }); // Hi Larry!Reassign keys
function printCoordinates({ left: x, top: y }) { console.log(`x: ${x}, y: ${y}`);}printCoordinates({ left: 25, top: 90 });This example assigns x to the value of the left key
Loop
for (let {title, artist} of songs) { ···}Assignment expressions also work in loops
Object Deconstruction
const { id, ...detail } = song;Use the rest(...) operator to extract some keys individually and the rest of the keys in the object
Spread Operator {.cols-2}
Object Extensions
with object extensions
const options = { ...defaults, visible: true,};No object extension
const options = Object.assign({}, defaults, { visible: true });The object spread operator allows you to build new objects from other objects. See: Object Spread
Array Expansion
with array extension
const users = [ ...admins, ...editors, 'rstacruz']No array expansion
const users = admins.concat(editors).concat(["rstacruz"]);The spread operator allows you to build new arrays in the same way. See: Spread operator
Functions
Function parameters {.row-span-3}
Default parameters
function greet(name = "Jerry") { return `Hello ${name}`;}Rest parameters
function fn(x, ...y) { // y is an array return x * y.length;}Extensions
fn(...[1, 2, 3]);//same as fn(1, 2, 3)Default (default), rest, spread (extension). See: function parameters
Arrow function {.row-span-3}
Arrow functions
setTimeout(() => { ···})with parameters
readFile('text.txt', (err, data) => { ...})implicit return
arr.map(n => n*2)//no curly braces = implicit return//Same as: arr.map(function (n) { return n*2 })arr.map(n => ({ result: n*2}))//Implicitly returning an object requires parentheses around the objectLike a function, but preserves this. See: Arrow functions
Parameter setting default value
function log(x, y = "World") { console.log(x, y);}
log("Hello"); // Hello Worldlog("Hello", "China"); // Hello Chinalog("Hello", ""); // HelloUsed in conjunction with destructuring assignment defaults
function foo({ x, y = 5 } = {}) { console.log(x, y);}
foo(); // undefined 5name attribute
function foo() {}foo.name; // "foo"length property
function foo(a, b) {}foo.length; // 2Objects
Shorthand Syntax
module.exports = { hello, bye };same below:
module.exports = { hello: hello, bye: bye,};method
const App = { start() { console.log("running"); },};//Same as: App = { start: function () {···} }Getters and setters
const App = { get closed () { return this.status === 'closed' }, set closed (value) { this.status = value ? 'closed' : 'open' }}Computed property name
let event = "click";let handlers = { [`on${event}`]: true,};//Same as: handlers = { 'onclick': true }Extract value
const fatherJS = { age: 57, name: "Zhang San" }Object.values(fatherJS)//[57, "Zhang San"]Object.entries(fatherJS)//[["age", 57], ["name", "Zhang San"]]Modules module
Imports import
import "helpers";//aka: require('···')import Express from "express";//aka: const Express = require('···').default || require('···')import { indent } from "helpers";//aka: const indent = require('···').indentimport * as Helpers from "helpers";//aka: const Helpers = require('···')import { indentSpaces as indent } from "helpers";//aka: const indent = require('···').indentSpacesimport is the new require(). See: Module imports
Exports export
export default function () { ··· }//aka: module.exports.default = ···export function mymethod () { ··· }//aka: module.exports.mymethod = ···export const pi = 3.14159;//aka: module.exports.pi = ···const firstName = "Michael";const lastName = "Jackson";const year = 1958;export { firstName, lastName, year };export * from "lib/math";export is the new module.exports. See: Module exports
as keyword renaming
import { lastName as surname // import rename} from './profile.js';
function v1() { ... }function v2() { ... }
export { v1 as default };//Equivalent to export default v1;
export { v1 as streamV1, // export rename v2 as streamV2, // export rename v2 as streamLatestVersion // export rename};Dynamically load modules
button.addEventListener("click", (event) => { import("./dialogBox.js") .then((dialogBox) => { dialogBox.open(); }) .catch((error) => { /*Error handling */ });});ES2020 Proposal introduce import() function
import() allows module paths to be dynamically generated
const main = document.querySelector("main");
import(`./modules/${someVariable}.js`) .then((module) => { module.loadPageInto(main); }) .catch((err) => { main.textContent = err.message; });import.meta
ES2020 Added a meta property import.meta to the import command,
which returns the meta information of the current module
new URL("data.txt", import.meta.url);In the Node.js environment, import.meta.url always returns a local path, that is, a string of the file:URL protocol,
such as file:/// home/user/foo.js
Import Assertions {.col-span-2}
static import
import json from "./package.json" assert { type: "json" };//Import all objects in the json fileDynamic Import
const json = await import("./package.json", { assert: { type: "json" } });Generators
Generator function
function* idMaker() { let id = 0; while (true) { yield id++; }}let gen = idMaker();gen.next().value; // → 0gen.next().value; // → 1gen.next().value; // → 2it’s complicated. See: Generators
For..of + iterator {.row-span-2}
let fibonacci = { [Symbol.iterator]() { let pre = 0, cur = 1; return { next() { [pre, cur] = [cur, pre + cur]; return { done: false, value: cur }; }, }; },};
for (var n of fibonacci) { // truncate sequence at 1000 if (n > 1000) break; console.log(n);}For iterating over generators and arrays. See: For..of iteration
Relationship with Iterator interface
var gen = {};gen[Symbol.iterator] = function* () { yield 1; yield 2; yield 3;};
[...gen]; // => [1, 2, 3]The Generator function is assigned to the Symbol.iterator property, so that the gen object has the Iterator
interface, which can be traversed by the ... operator
Symbol.iterator property
function* gen() { /*some code */}var g = gen();
g[Symbol.iterator]() === g; // truegen is a Generator function, calling it will generate a traverser object g. Its Symbol.iterator property, which
is also an iterator object generation function, returns itself after execution
see also
- Learn ES2015(babeljs.io)
- ECMAScript 6 Features Overview (github.com)