18 Years of Specifications
ECMAScript 1 through 5
-
Precursor
- Brendan - Mocha
- Netscape codenames LiveScript
- Netscape announces JavaScript (1995)
- Netscape releases JavaScript (1996)
- 1 ECMA establishes specification (1997)
- 2 ISO/IEC 16262 I18N (1998)
- 3 RegExp, String formatting, try/catch, errors (1999)
- 4 failure, arguing, punted and renamed Harmony (1999-2009)
- 5 ‘use strict’, JSON, get, set, reflection (2009)
- 5.1 international standardization (2011)
Transpiling
- Firefox, Chrome hot on tail
- GWT/Type/Clojure/Dart/Coffee/JSX history
- Compiling to ES5
- ES6 via Babel (71%) or Traceur (58%)
- Mana began development with ES6 via Babel
- ES6 gets standardized (June 2015)
Constants
- Immutable Variables
const e = 2.718281828459045;
const π = 3.141592653589793;
e < π; // → true
e = π; // → Line 4: "e" is read-only
Scoping
- Block-Scoped Variables
let a = [ 1 ];
for (let i = 0; i < a.length; i++) {
let x = a[i] + 1;
}
console.log(i, x, a); // → i is not defined, x is not defined, [1]
- Block-Scoped Functions
{
function foo () { return 'hello'; }
foo(); // → hello
{
function foo () { return 'world'; }
foo(); // → world
}
foo(); // → hello
}
Arrow Functions
- Expression Bodies
let admins = collection.map( m => m.get("admin") );
console.log(m); // → m is not defined
- Statement Bodies
- Lexical this
this.accepted = [];
this.collection.each((m) => {
if (m.get("state") === "accepted")
this.accepted.push(m);
});
Extended Parameter
- Defaults
- Rest Parameter
{
initialize: function(options = {}) {
_(this.defaults).extend(options);
},
generateName: function(conversation, names...) {
console.log(names); // → ["Angie", "Ariel", "Jared"]
conversation.set("name", names.join(", "));
}
}
- Spread Operator
var params = [ "kana", [true], 7 ];
[ 1, 2, ...params ].length; // → 5
Template Strings
- String Interpolation
var lastSeenAt = `Last Seen ${manawa(this.model.get("sent_at"))}`;
- Multiline support
console.log(`Aloha
Hawaii`); // → Aloha Hawaii
- Raw String Access
String.raw `Hi, \n World ${ 42 }` === "Hi, \\n World 42"; // → true
Extended Literals
- Binary and Octal
0b110010100 === 404; // → true
- Unicode String/RegExp
"\u{0CA0}_\u{0CA0}" === "ಠ_ಠ" // → true
Enhanced Regular Expression
- Sticky Matching
- Efficient Parsing
let regex = /foo.bar/gy;
regex.sticky; // → true
regex.lastIndex; // → 0
regex.test('foo-bar'); // → true
regex.lastIndex; // → 7
regex.test('..foo-bar'); // → false
regex.lastIndex = 2;
regex.test('..foo-bar'); // → true
regex.lastIndex; // → 9
Enhanced Object Properties
- Property Shorthand
var options = { animate, duration };
- Computed Property Names
- Method Properties
var properties = {
color: "blue",
[ "avatar_" + getSize() ]: 42
};
var helpers = {
foo (a, b) {
// …
},
*quux (x, y) {
// …
}
};
Destructuring Assignment
- Array Matching
var list = [ "Blue", "Red", "Yellow" ];
var [ first, , second ] = list;
[ second, first ] = [ first, second ];
- Object Matching (Deep)
var { members, meta: { total_count, updated_at } } = payload();
- Parameter Matching
function sum ([ x, y ]) { return x + y; }
function msgText ({ name, body }) { return `${name}: ${body}`; }
- Fail-Soft with Defaults
var [ a = 1, b = 2, c = 3, d ] = [ 4, 5 ];
Modules
- Export
export function randomNumber {
return Math.floor( Math.random() * 11 );
}
- Import
import { Input, Label } from "react-bootstrap";
- Default
export default (x) => x * x;
- Wildcard
import * as _ from "underscore";
Classes
- Declaration / Inheritance
- Expressions
- Base Class Access
- Static Members
- Getters / Setters
class Group extends Party {
constructor (name, color) {
super(name);
this.color = color;
}
static defaultGroup () {
return new Group("Engineering", "#232b38");
}
set name (name) { this._name = name; }
get name () { return this._name; }
get color () { return this._color; }
}
var engineering = Group.defaultGroup();
engineering.color === "#232b38"
Symbol Type
- Unique
- Immutable
- Optional Descriptions (debug)
let attributes = {};
const avatar = Symbol();
attributes[avatar] = new Avatar();
typeof avatar // → "symbol"
Object.getOwnPropertySymbols(attributes); // → [ avatar ]
Symbol("avatar") === Symbol("avatar"); // → false
- Global Symbols
let globalAvatar = Symbol.for("avatar");
globalAvatar === Symbol.for("avatar"); // → true
Symbol.keyFor(globalAvatar); // → avatar
Iterators
- Iterable Protocol
let fibonacci = {
[Symbol.iterator]() {
let pre = 0, cur = 1;
return {
next () {
[ pre, cur ] = [ cur, pre + cur ];
return { done: false, value: cur };
}
};
}
};
- For _ of _
for (let n of fibonacci) {
if (n > 1000) break;
console.log(n);
}
Generators
- Iterator Protocol
- Direct
- Matching
- Control-Flow
function* range (start, end, step) {
while (start < end) {
yield start;
start += step;
}
}
let evens = range(0, 10, 2);
console.log(evens.next().value); // → 0
for (let n of evens) {
console.log(n); // → 2, 4, 6, 8
}
Data Structures
- Sets
let alphabet = new Set();
alphabet.add("A").add("B").add("A");
alphabet.size; // → 2
alphabet.has("A"); // → true
for (let key of alphabet.values()) // insertion order
console.log(key);
- Maps
let member = new Map();
member.set("id", 42);
member.set(state, "accepted");
member.get(state); // → "accepted"
member.size; // → 2
for (let [ key, val ] of member.entries())
console.log(key + " = " + val);
Typed Arrays
- Arbitrary byte-based data structures
- Network Protocols
- Cryptography Algorithms
- File Format Manipulations
let buffer = new ArrayBuffer(24); // generic
let amountDue = new Float32Array(buffer, 20, 1);
let imageData = new Uint8ClampedArray([42, 1337]);
console.log(imageData[1]); // → 255
Additional Built-in Methods
- Object Property Assignment
- Array Element Finding
- String Repeating and Searching
- Number Type and Safety Checking
- Number Comparison / Truncation / Sign Determination
Object.assign({a: 1}, {b: 2}, {c: 3}); // → { a: 1, b: 2, c: 3 }
[ 1, 3, 4, 2 ].find(x => x > 3); // → 4
"aloha".repeat(3); // alohaalohaaloha
"/networks/lua/latest".includes("networks"); // → true
"reddit".endsWith("it"); // → true
"facebook".startsWith("face"); // → true
Number.isNaN(NaN); // → true
Number.isFinite(Infinity); // → false
Number.isSafeInteger(10007199254740992); // → false
Number.EPSILON; // instead of 2.22e-16
Math.trunc(-42.7); // → -42
Math.sign(-7); // → -1
Promises
- Async Callback
- Chaining
let networkPromises = this.networks.each((network) => {
return new Promise((resolve, reject) => {
return network.fetch((response) => {
if (response.body) {
resolve(response.body);
} else {
reject(response.error);
}
});
});
});
Promise.all(networkPromises).then((data) => {
NetworkActions.setNetworks(data);
}, (error) => {
errorHandler(error);
});
Meta Programming
- Proxying
var artist = { name: "Michelangelo", paintings: 253 };
var interceptor = {
set: function (receiver, property, value) {
console.log(property, 'is changed to', value);
receiver[property] = value;
}
};
artist = Proxy(artist, interceptor);
artist.paintings = 254; // → paintings is changed to 254
- Reflection
let obj = { a: 1 };
Object.defineProperty(obj, "b", { value: 2 });
obj[Symbol("c")] = 3;
Reflect.ownKeys(obj); // → [ "a", "b", Symbol(c) ]
What is next?
-
ES7
- Object.observe
- Async (Event Loop Concurrency)
- Comprehensions
- Guards (user defined invariants!)
-
ES8
- a long ways out
- Macros (make your own syntax)
- Parallel arrays
Finito
- Compatibility Table: https://kangax.github.io/compat-table/es6/
- Future of JS: https://www.2ality.com/2011/09/es6-8.html
- REPL: https://babeljs.io/repl/#?experimental=true
- Feature List https://es6-features.org