 
	Ondřej Žára, @0ndras
 
 
Also known as The Callback Hell
getData(function(err, data) {
	if (err) return displayError(err)
	processData(data, function(err, result) {
		if (err) return displayError(err)
		displayData(result, function(err) {
			if (err) return displayError(err)
		})
	})
})
Readable, but gets hairy when additional arguments are passed to individual callbacks
getData().then(
	processData,
	displayError
).then(
	displayData,
	displayError
).then(
	null,
	displayError
)
Readable, but needs the additional MAGIC boilerplate that runs the generator and correctly links returned promises
let generator = function* () {
	try {
		let data = yield getData()
		let result = yield processData(data)
		yield displayData(result)
	} catch (err) {
		displayError(err)
	}
}
MAGIC(generator)
The async keyword defines an async function:
async function A() {}
let B = async function() {}
let obj = { async C() {} }
let D = async () => {}
	The await keyword can only be used inside of an async function:
async function A() {
	let b = await B()
	let c = await C(b)
	return c
}
	await does nothingawait interrupts the execution and waits for fulfillmentawait throwsPromise-based code as readable as its synchronous counterpart
try {
	let data = await getData()
	let result = await processData(data)
	return displayData(result)
} catch (err) {
	displayError(err)
}
Parallel execution in JavaScript:
Passing data between Workers:
let sab = new SharedArrayBuffer(10) // bytes
worker.postMessage(sab)
let view = new Uint8Array(sab)
view[0] = 42 // will be eventually visible from the worker
SharedArrayBuffers correspond to a memory that is truly shared across multiple workers (threads)view[0] = view[0] + 1 // Race Conditions 101The Atomics namespace holds functions that operate on SharedArrayBuffers
| load(),store() | get/set values without instruction reordering | 
| add(),sub(),and(),or(),xor() | atomic arithmetics | 
| exchange(arr, index, value) | sets a new value, returns the old one | 
| exchangeCompare(arr, index, | sets a new value if the old one matches the expected one | 
| wait(arr, index, value, [timeout]) | blocks until a value is no longer present | 
| wake(arr, index, count) | wakes a given number of waiters | 
JS objects can be iterated in multiple ways:
for (let p in obj) {}Object.keys(obj)Object.getOwnPropertyNames(obj)All these variants iterate over property names (strings)
Object.values(obj)
Object.keys)Object.entries(obj)
What are property descriptors?
let descriptor = {
	enumerable: false,
	get: Math.random
}
Object.defineProperty(myObj, "key", descriptor)
Object.defineProperties(myObj, {"key":descriptor})
Object.create(proto, {"key":descriptor})
Object.getOwnPropertyDescriptor(obj, "key")Object.getOwnPropertyDescriptors(obj)Object.definePropertiesWhere are trailing commas already allowed (and ignored)?
[a, b, c, ]{key: value, }New in ES2017: argument lists
function x(a, b, c, )x(a, b, c, )| When | Event | 
| November 2015 | First draft of the padStart/padEndproposal | 
| March 2016 | left-padincident | 
| June 2017 | padStart/padEndaccepted into the standard | 
Method names are chosen to be independent on writing direction
"test".padStart(7, "!?") // "!?!test"
"test".padEnd(7)         // "test   "