ES6
NEW
BUILTIN
APIs
'blah'.includes('la'); // true
'blah'.startsWith('bl'); // true
'blah'.endsWith('lah'); // true
'blah'.repeat(3); // "blahblahblah"
String
(selected examples)
Number.isNaN('NaN'); // false
/* vs */ isNaN('NaN'); // true
Number.isFinite('0'); // false
/* vs */ isFinite('0'); // true
Number
"Modularization of Globals"
(selected examples)
var array = [1, 2, 3, 4, 5];
array.copyWithin(1, 3); // [1, 4, 5, 4, 5]
array.fill(42); // [42, 42, 42, 42, 42]
Array
(selected examples)
Object.is(0, -0); // false
/* vs */ 0 === -0; // true
/* Say goodbye to _.extend() */
Object.assign({}, {name: 'moe'}, {age: 15});
// {name: "moe", age: 15}
Object
(selected examples)
var options = Object.assign({}, defaults, overrides);
/* vs */
var options = Object.assign(Object.create(defaults), overrides);
Object.assign()
Pros
- Smaller Memory Footprint
- Better Performance
- Dynamic Defaults
Cons
- May cause subtle issues
Beware of methods that only work with own properties, eg:
Object.keys(), JSON.stringify()
var bird = {status: 'awake', mood: 'happy'};
Object.observe(bird, changes => console.log(changes));
bird.color = 'red';
bird.status = 'asleep';
delete bird.mood;
/*
[
{"type":"add","object":{"status":"asleep","color":"red"},"name":"color"},
{"type":"update","object":{"status":"asleep","color":"red"},"name":"status","oldValue":"awake"},
{"type":"delete","object":{"status":"asleep","color":"red"},"name":"mood","oldValue":"happy"}
]
*/
Object.observe()
Actually, this is part of ES7, but you can find it in the latest Chrome.
=>
Noticed the weird arrow?
UNBURDEN
FUNCTION
KEYWORD
THE
The function keyword
has been used for too many things.
function Cat(name) {
this.name = name;
}
Cat.prototype.meow = function() {
return 'Meow';
};
Cat.prototype.do = function(task, callback) {
console.log(this.meow() + ', I am ' + this.name +
', and I was born to ' + task + '!');
return callback();
};
var nyan = new Cat('Nyan');
nyan.do('fly', function() {
console.log('===FLY===');
});
TIME
to
UNRAVEL
the
RAVEL
function Cat(name) {
this.name = name;
}
Cat.prototype.meow = function() {
return 'Meow';
};
Cat.prototype.do = function(task, callback) {
console.log(this.meow() + ', I am ' + this.name +
', and I was born to ' + task + '!');
return callback();
};
var nyan = new Cat('Nyan');
nyan.do('fly', function() {
console.log('===FLY===');
});
Constructor
Methods
Callback
function Cat(name) {
this.name = name;
}
Cat.prototype.meow = function() {
return 'Meow';
};
Cat.prototype.do =
function(task, callback) {
console.log(this.meow() +
', I am ' +
this.name +
', and I was' +
'born to ' +
task + '!');
return callback();
};
class Cat {
constructor(name) {
this.name = name;
}
meow() {
return 'Meow';
}
do(task, callback) {
console.log(this.meow() +
', I am ' +
this.name +
', and I was' +
'born to ' +
task + '!');
return callback();
}
}
nyan.do('fly', function() {
console.log('===FLY===');
});
nyan.do('fly',
() => console.log('===FLY==='));
Super
class SkinnedMesh extends THREE.Mesh {
constructor(geometry, materials) {
super(geometry, materials);
this.idMatrix = SkinnedMesh.defaultMatrix();
this.bones = [];
this.boneMatrices = [];
//...
}
update(camera) {
//...
super.update();
}
static defaultMatrix() {
return new THREE.Matrix4();
}
}
Mixins / Traits
import traits from 'es6-traits';
import React from 'react/addons';
export const {on, using} = traits();
export const autobind = {
[Symbol.toStringTag]: 'autobind',
constructor() {
Object.getOwnPropertyNames(this.constructor.prototype)
.filter(x => x.startsWith('on'))
.map(x => this[x] = this[x].bind(this));
}
};
export const purerender = Object.assign(React.addons.PureRenderMixin, {
[Symbol.toStringTag]: 'purerender'
});
import React from 'react';
import {on, using, autobind, purerender} from './traits';
export default class SomeComponent extends (
on (React.Component), using (autobind, purerender)
) {
...
}
NEW
PRIMITIVE
Symbols
const CONSTANTS = {
DISPATCHER: {
CLIENT_ACTION: Symbol(),
SERVER_ACTION: Symbol()
}
};
Well-known Symbols
Symbol.hasInstance
Symbol.isConcatSpreadable
Symbol.isRegExp
Symbol.iterator
Symbol.toPrimitive
Symbol.toStringTag
Symbol.unscopables
ENHANCED
LITERALS
Binary and Octal Literals
0b111110111 === 503 // true
0o767 === 503 // true
Object Literals
var obj = {
// __proto__
__proto__: theProtoObj,
// Shorthand for ‘handler: handler’
handler,
// Methods
toString() {
// Super calls
return "d " + super.toString();
},
// Computed (dynamic) property names
[ "prop_" + (() => 42)() ]: 42
};
Template Literals
// Interpolate variable bindings
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`
// Construct an HTTP request prefix is used to
// interpret the replacements and construction
GET`http://foo.org/bar?a=${a}&b=${b}
Content-Type: application/json
X-Credentials: ${credentials}
{ "foo": ${foo},
"bar": ${bar}}`(myHandler);
Functional
Programming
Goodies
Destructuring
var [a, , b] = [1,2,3]; // list matching
var { op: a, lhs: { op: b }, rhs: c }
= getASTNode(); // object matching
// object matching shorthand
var {op, lhs, rhs} = getASTNode();
// Can be used in parameter position
function g({name: x}) {
console.log(x);
}
g({name: 5})
// Fail-soft destructuring
var [a] = [];
a === undefined;
// Fail-soft destructuring with defaults
var [a = 1] = [];
a === 1;
Rest / Spread
function f(x, ...y) {
// y is an Array
return x * y.length;
}
f(3, "hello", true) == 6
function f(x, y, z) {
return x + y + z;
}
// Pass each elem of array as argument
f(...[1,2,3]) == 6
Tail Calls
function factorial(n, acc = 1) {
"use strict";
if (n <= 1) return acc;
return factorial(n - 1, n * acc);
}
// Stack overflow in most implementations today,
// but safe on arbitrary inputs in eS6
factorial(100000)
D&C
(target, source, ...rest) => {
return !source ? target :
!rest.length ? target.reduce((m, n, k) => {
const ratio = ~~(target.length / source.length),
item = source[~~(k / ratio)];
return !item ? m.concat(n) :
(k + 1) % ratio ? m.concat(n) :
m.concat(n, item);
}, []) :
interleave(interleave(target, source), ...rest);
}
WE HAVE
MODULES
NOW
Import / Export
import * as math from "lib/math";
import exp, {pi, e} from "lib/mathplusplus";
export * from "lib/math";
export var e = 2.71828182846;
export default function(x) {
return Math.exp(x);
}
OTHER
GOODIES
Let / Const
function f() {
{
let x;
{
// okay, block scoped name
const x = "sneaky";
// error, const
x = "foo";
}
// error, already declared in block
let x = "inner";
}
}
Iterators + For..Of
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 the sequence at 1000
if (n > 1000)
break;
console.log(n);
}
Generators
var fibonacci = {
[Symbol.iterator]: function*() {
var pre = 0, cur = 1;
for (;;) {
var temp = pre;
pre = cur;
cur += temp;
yield cur;
}
}
}
for (var n of fibonacci) {
// truncate the sequence at 1000
if (n > 1000)
break;
console.log(n);
}
Array / Generator
Comprehensions
// Array comprehensions
var results = [
for(c of customers)
if (c.city == "Seattle")
{ name: c.name, age: c.age }
];
// Generator comprehensions
var results = (
for(c of customers)
if (c.city == "Seattle")
{ name: c.name, age: c.age }
);
Map + Set +
WeakMap + WeakSet
// Sets
var s = new Set();
s.add("hello").add("goodbye").add("hello");
s.size === 2;
s.has("hello") === true;
// Maps
var m = new Map();
m.set("hello", 42);
m.set(s, 34);
m.get(s) == 34;
ES6: Not Yo Momma's JavaScript
By G. Kay Lee
ES6: Not Yo Momma's JavaScript
- 6,395