WELCOME TO THE JUNGLE
Why Transpile?
Transpilation is complicated
Well, yes, but...
So is updating Javascript
Lots of moving parts
Disruptive to workflow
WTF
Turns out, languages are hard.
Regexes!
Try/catch!
switch!
ES3 brought...
Function binding!
Functional Array Methods
Defined Properties
ES5 brought...
ES6 will bring...
Fat Arrows!
Destructuring!
Rest Parameters!
Spread Operators!
Default Parameters!
Block-level bindings!
Template Strings!
Generators!
Classes!
Proxies!
Maps! Sets!
Promises!
Symbols!
Function names!
New Static Methods!
Proper Tail Call Optimization!
ES6⇒ES2015
ES7⇒ES2016
???⇒???
So Why Not ES6?
Cuz they said so
So What Can I Do?
(glad you asked)
Limitations
Some things we just can't make happen in ES5 alone
But we can get pretty close...
Block-level Bindings
Block-level Bindings
Block-level Bindings
is even scoped to plain blocks
let
Block-level Bindings
const foo = "I AM CONSTANT AS THE NORTHERN STAR";
foo = "NO UR NOT"; // Will not compile -- "foo" is read-only
const foo = {
foo: 'bar'
};
foo.foo = 'baz'; // This is valid
foo = { foo: 'baz' }; // This is not
Consts are pretty nifty, too
Default Parameters
Shorthand defaults are simple, but dangerous!
Default parameters are good!
Rest & Spread
Rest & Spread
if (someBusinessLogic(data)) {
return performSomeAction(data);
} else if (someOtherBusinessLogic(data, metadata)) {
return performSomeAction(data, metadata);
}
let args;
if (someBusinessLogic(data)) {
args = [data];
} else if (someOtherBusinessLogic(data, metadata)) {
args = [data, metadata];
}
return performSomeAction(...args);
mise-en-place programming
Fat Arrows
Simplify one-line methods
Even use them with multi-line methods
Fat Arrows
.bind(this)
.bind(this)
.bind(this)
Fat Arrows
Now all sexy and clean-looking
Fat Arrows
{
inheritedFunction: function() {
someAsynchronousTask().then(function() {
this.inherited(arguments);
}.bind(this));
}
}
{
inheritedFunction: function() {
var _args = arguments;
someAsynchronousTask().then(function() {
this.inherited(_args);
}.bind(this));
}
}
{
inheritedFunction: function() {
someAsynchronousTask().then(() => this.inherited(arguments));
}
}
Destructuring
Just suck values right out of an array
You can even do it with objects
WHY NOT STRINGS?
Destructuring
Defaults
Parameters
Object Shorthand
Destructuring
Template Strings
Template Strings
Expressions can also be substituted
Template Strings
Tagged Template Literals are crazy, but very interesting
Template Strings
Maps & Sets
var obj = {};
obj.foo = 'foo';
obj.bar = 'bar';
'bar' in obj; // true
for (let k in obj) {
console.log(obj[k], k);
}
// foo foo
// bar bar
delete obj.bar;
var map = new Map();
map.set('foo','foo');
map.set('bar','bar');
map.has('bar'); // true
map.forEach((value, key) =>
console.log(key, value));
// foo foo
// bar bar
map.delete('bar');
map.clear();
map.set('foo', 'foo')
.set('bar', 'bar')
.set('baz', 'baz')
.set('quux', 'quux');
let arbitrary_object = { lorem: 'ipsum' };
map.set(arbitrary_object, 'holy cow!');
map.size; // 5
Maps & Sets
var list = [];
list.push(1);
list.push(2);
list.push(3);
list.push(2);
list.length === 4; // true
for (let value of list) {
console.log(value);
}
// 1
// 2
// 3
// 2
var set = new Set();
set.add(1);
set.add(2);
set.add(3);
set.add(2);
set.size === 3; // true
set.forEach(value => console.log(value));
// 1
// 2
// 3
set.delete(1);
set.clear();
set.add(1)
.add(2)
.add(3);
let arbitrary_object = { lorem: 'ipsum' };
set.add(arbitrary_object);
set.has(1); // true
Maps & Sets
Maps and Sets are great
BUT
WHAT ABOUT MEMORY?
WeakMaps & WeakSets
let set = new WeakSet();
set.add(arbitrarily_large_object); // The object is loaded into WeakSet
// just like Set, but now can still
// be garbage collected
set.add(3); // TypeError! WeakMaps & WeakSets *MUST* use Objects.
set.size; // Nonexistent!
set.has(arbitrarily_large_object); // true
let map = new WeakMap();
map.set(arbitrarily_large_object, any_other_value);
map.set(3, any_other_value); // TypeError!
map.size; // Nonexistent!
map.has(arbitrarily_large_object); // true
Symbols
Symbols
Generators
function range(min, max, callback) {
for (let i = min; i <= max; i++) {
callback(i);
}
}
range(2, 3, (i) => console.log(`calling for ${i}: `))
// calling for 2
// calling for 3
function* range(min, max) {
for (let i = min; i <= max; i++) {
yield i;
}
}
for (let i of range(2, 3)) {
console.log(`calling for ${i}`);
}
// calling for 2
// calling for 3
Generators
for-of
lets you iterate over values of an iterable
Generators
function* range(min, max) {
for (let i = min; i <= max; i++) {
yield i;
}
}
let generator = range(2,3);
/**
* generator ~= {
* next: function() { [native code] },
* throw: function() { [native code] },
* return: function() { [native code] }
* }
*/
Generators
let result = generator.next();
/**
* result = {
* value: 2,
* done: false
* }
*/
result = generator.next();
/**
* result = {
* value: 3,
* done: false
* }
*/
result = generator.next();
/**
* result = {
* done: true
* }
*/
Generators
can also inject values into a function
yield
Generators
Generators
Generators
Generators
Generators
Generators
Want to iterate over your objects?
Generators
Spread works great with any Iterable
Promises
Promises
Promise.all
Promises
Promise.race
Async/Await
What about things
we're not using?
Good question.
Classes
Classes
Proxies
let original = {};
let proxy = new Proxy(original, {
get: function(original, key, proxy) {
console.log(`looking for ${key} in the original object`);
if (key in original) {
return original[key];
} else {
return original[key] = 42;
}
},
set: function(original, key, value) {
console.log(`trying to set ${key} to ${value}`);
if (key in original) {
return original[key] = value;
} else {
throw new TypeError('Cannot set a nonexistent property through this proxy');
}
}
});
proxy.foo; // 42
proxy.foo = 30; // 30
try {
proxy.bar = 'FAIL'; // TypeError: Cannot set a nonexistent property through this proxy
} catch (e) {
console.log('broke because', e.message);
}
proxy.bar; // 42
proxy.bar = 'WIN'; // 'WIN'
BabelJS REPL: https://goo.gl/Tv9Ebr
Native Modules
import Foo from "aFooModule";
import Bar from "aBarModule";
import * as ChangedName from "anotherModule";
import { map, zip } from "utils/lodash";
// ... do something with these dependencies
export default {
myNewModule,
otherItems
};
export class MyClass {
// ...
}
export function relatedToMyClass() { ... }
let foo = 'bar';
export foo;
Function Binding
Function Binding
Bound Native Methods on Github
Object Spread Operator
Decorators
WELCOME TO THE JUNGLE
By Mike McElroy
WELCOME TO THE JUNGLE
- 1,208