operator • Bind this context to a function, by desugaring to bind, call, or apply. • https://github.com/zenparsing/es-function-bind • http://blog.jeremyfairbank.com/javascript/ javascript-es7-function-bind-syntax/
{ foo: 'bar' }; logThis.call(obj); // { foo: 'bar' } // Now obj::logThis(); // { foo: 'bar' } Normal invocations would log window or the global object.
and bind. • Virtual methods • Use array methods on DOM node lists. • Object method chaining with real methods and third party libs like Trine. • https://github.com/jussi-kalliokoski/trine • Callbacks to other libraries.
statement in the block is the “return” value. • Prepend do keyword to a block to create. • Like syntactical sugar for IIFE. • http://wiki.ecmascript.org/doku.php?id=strawman:do_expressions
'b'; const y = 'a'; const z = 'r'; x + y + z; }; console.log(foo); // bar console.log(do { const x = 21; x * 2; }); // 42 Last statement is return value.
if (ready) "I'm ready. Let's go!"; else "Hold on a minute."; }; console.log(response); } readyResponse(true); // I'm ready. Let's go! readyResponse(false); // Hold on a minute.
if (ready) "I'm ready. Let's go!"; else "Hold on a minute."; }; console.log(response); } readyResponse(true); // I'm ready. Let's go! readyResponse(false); // Hold on a minute. Each branch ends with an expression.
• Use @ and an expression that evaluates to a function. • Decorator precedes a class or method definition. • https://github.com/wycats/javascript-decorators
= 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 Consequence: getters are nonenumerable by default.
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.
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. Evaluate function call and use return value as decorator.
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.
legs`); } }; @mixin(Quadrupedal, EventEmitter.prototype) class Dog { constructor(name, age) { this.name = name; this.age = age; } haveBirthday() { this.age++; this.emit('birthday', this); } } Use a decorator on the class
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
class/property modification. • Mixins — no more fragile base class or multiple inheritance issues. • @autobind, @deprecate, @memoize, @readonly, and more! • https://github.com/jayphelps/core-decorators.js
} function loadOrder(orderId) { const promise = Promise.resolve( fetchJson(`/orders/${orderId}`) ); return promise.then(order => { console.log(order); return Promise.resolve(undefined); }); } What does this function look like?
[]; for (const id of orderIds) { const order = await fetchJson(`/orders/${id}`); orders.push(order); } console.log(orders); } loadOrders([1, 2, 3]); Each step of loop has to wait. Issue if requests aren’t dependent on each other.
await Promise.all(orderIds.map(id => { return fetchJson(`/orders/${id}`); })); console.log(orders); } loadOrders([1, 2, 3]); Make all requests at once and resolve with Promise.all. Allows for parallelism.