Stage 0 - Strawman • Informal idea or proposal for change or addition. • Function bind operator • Do expressions foo::bar(); let y = do { let x = 40; x + 2; }
Stage 1 - Proposal • Make a case for addition by describing use cases, challenges, high-level API. • Class and property decorators class Foo { @memoize bar() { return 42; } }
Class Decorators • Annotate and modify classes and their properties. • Use @ and an expression that evaluates to a function. • Decorator precedes a class or method definition. • github.com/wycats/javascript-decorators
class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } get fullName() { return `${this.firstName} ${this.lastName}`; } } const p = new Person('Jeremy', 'Fairbank'); for (const key in p) { console.log(`${key}: ${p[key]}`); } // firstName: Jeremy // lastName: Fairbank Getters are nonenumerable by default.
function enumerable(target, name, descriptor) { descriptor.enumerable = true; return descriptor; } Object being modified (e.g. prototype or a class based on usage)
function enumerable(target, name, descriptor) { descriptor.enumerable = true; return descriptor; } Object literal defining the property that will be added to target
function enumerable(target, name, descriptor) { descriptor.enumerable = true; return descriptor; } Optional if you mutate descriptor. Useful if you want to create new descriptor.
class Person { constructor(name) { this.name = name; } @alias('sayHello') greet() { console.log(`Hello. My name is ${this.name}.`); } } const person = new Person('Jeremy'); person.greet(); // Hello. My name is Jeremy. person.sayHello(); // Hello. My name is Jeremy.
const dog = new Dog('Tucker', 8); dog.on('birthday', d => { console.log(`${d.name} just turned ${d.age}`); }); dog.haveBirthday(); // Tucker just turned 9 dog.walk(); // Tucker walks with four legs
const dog = new Dog('Tucker', 8); dog.on('birthday', d => { console.log(`${d.name} just turned ${d.age}`); }); dog.haveBirthday(); // Tucker just turned 9 dog.walk(); // Tucker walks with four legs From EventEmitter From Quadrupedal
Why Class Decorators? • Extremely powerful and expressive syntax for class/property modification. • Mixins — avoid fragile base class or multiple inheritance issues. • @autobind, @deprecate, @memoize, @readonly, and more! • github.com/jayphelps/core-decorators.js
Object Rest and Spread • Gives objects rest and spread capabilities like arrays in ES6. • Use ... operator. • Rest operation is like pick function in lodash or a clone function. • Spread operation is like syntactical sugar for Object.assign. • github.com/sebmarkbage/ecmascript-rest-spread
Why Object Rest/Spread? • Succinct syntax instead of Object.assign calls. • Pick/omit object properties. • Clone objects. (WARNING: Not a deep clone.) • Provide overridable default options in a function.
Async Functions • Provide synchronous-like syntax for asynchronous code. • Prepend function with async. • Use await operator on a promise to obtain a fulfilled promise value. • github.com/tc39/ecmascript-asyncawait
async function printOrder(orderId) { const order = await fetchOrder(orderId); console.log(order); } printOrder(1); Await a promise and obtain the fulfilled/ resolved value. Nonblocking.
Wrap remaining code in a then callback. async function printOrder(orderId) { const promise = Promise.resolve( fetchOrder(orderId) ); console.log(order); } printOrder(1);
Sequential async function printOrders(orderIds) { const orders = []; for (const id of orderIds) { const order = await fetchOrder(id); orders.push(order); } console.log(orders); } printOrders([1, 2, 3]); Each step of loop has to wait. Issue if requests aren’t dependent on each other.
Parallel async function printOrders(orderIds) { const orders = await Promise.all( orderIds.map(id => fetchOrder(id)) ); console.log(orders); } printOrders([1, 2, 3]); Make all requests at once and resolve with Promise.all. Allows for “parallelism.”
Why Async Functions? • Synchronous-looking asynchronous code. • Gain back use of native language flow control constructs with asynchronous code (e.g. for..of, try/catch). • Asynchronous coroutines.