Created
September 23, 2016 15:20
-
-
Save JustinMorgan/e779835c0cfffc5252c52389221e028e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//--------------------------- Context-Binding Lambda Expressions ------------------------------------ | |
// Expression bodies | |
var evens = [2,4,6,8,10]; | |
var odds = evens.map(v => v + 1); | |
var nums = evens.map((v, i) => v + i); | |
var fives = []; | |
// Statement bodies | |
nums.forEach(v => { | |
if (v % 5 === 0) | |
fives.push(v); | |
}); | |
// Lexical this | |
var bob = { | |
_name: "Bob", | |
_friends: [], | |
printFriends() { | |
this._friends.forEach(f => | |
console.log(this._name + " knows " + f)); | |
} | |
}; | |
//--------------------------- Getters, Setters, and Computed Property Names ------------------------------------ | |
let log = ['test']; | |
let key = "foo" | |
let obj = { | |
get latest() { | |
if (log.length == 0) return undefined; | |
return log[log.length - 1] | |
}, | |
set [key](value) { //equivalent to set foo(value) {...} | |
//this[key] = value; //stack overflow | |
this.status = `${key} was set to ${value}`; | |
} | |
} | |
obj.foo = "bar"; | |
console.log("obj.latest: ", obj.latest); //obj.latest: test | |
console.log("obj: ", obj); //obj: {"latest":"test","status":"foo was set to bar"} | |
//--------------------------- Classes ------------------------------------ | |
class Polygon { | |
constructor(height, width) { | |
this.height = height; | |
this.width = width; | |
} | |
get area() { | |
return this.calcArea(); | |
} | |
calcArea() { | |
return this.height * this.width; | |
} | |
static get groupName() { | |
return "Shapes"; | |
} | |
} | |
console.log("Polygon.groupName: ", Polygon.groupName) //Polygon.groupName: Shapes | |
class Square extends Polygon { | |
constructor(length) { | |
// Here, it calls the parent class' constructor with lengths | |
// provided for the Polygon's width and height | |
super(length, length); | |
// Note: In derived classes, super() must be called before you | |
// can use 'this'. Leaving this out will cause a reference error. | |
this.name = 'Square'; | |
} | |
get area() { | |
return this.height * this.width; | |
} | |
set area(value) { | |
this.height = this.width = Math.sqrt(value); | |
this.area = value; | |
} | |
} | |
//-------------------- Implicit object member names -------------------------- | |
var foo = 1, | |
bar = 2, | |
baz = { foo, bar }; //property names default to the variable names they came from | |
console.log("baz: ", baz); //baz: {"foo":1,"bar":2} | |
//--------------------------- Enhanced Object Literals ------------------------------------ | |
var theProtoObj = {}, somethingElse = {}, handler = () => {}; | |
var obj = { | |
// Sets the prototype. "__proto__" or '__proto__' would also work. | |
__proto__: theProtoObj, | |
// Computed property name does not set prototype or trigger early error for | |
// duplicate __proto__ properties. | |
['__proto__']: somethingElse, | |
// Shorthand for ‘handler: handler’ | |
handler, | |
// Methods | |
toString() { | |
// Super calls | |
return "d " + super.toString(); | |
}, | |
// Computed (dynamic) property names | |
[ "prop_" + (() => 42)() ]: 42 | |
}; | |
//--------------------------- Destructuring ------------------------------------ | |
var [a, ,b] = [1,2,3]; // list destructuring | |
console.log("a: ", a) //a: 1 | |
console.log("b: ", b) //b: 3 | |
var c = {d:4, e:5, f:6} | |
var {d,e,f} = c; // object destructuring | |
console.log("d: ", d) //d: 4 | |
console.log("e: ", e) //e: 5 | |
console.log("f: ", f) //f: 6 | |
var [g] = []; //fail-soft: no exception thrown | |
console.log("g: ", g + "") //g: undefined | |
var [h = 1] = []; //use a default value | |
console.log("h: ", h + "") //h: 1 | |
// destructuring arguments | |
function i({name: x}) { | |
return x; | |
} | |
console.log("i({name: 5}): ", i({name: 5})) //i({name: 5}): 5 | |
// destructuring arguments with implicit property names and default values | |
function j({x, y, w = 10, h = 10}) { | |
return x + y + w + h; | |
} | |
console.log("j({x:1, y:2}): ", j({x:1, y:2})) //j({x:1, y:2}): 23 | |
//--------------------------- Default + Rest + Spread ------------------------------------ | |
function f(x, y=12) { | |
// y is 12 if not passed (or passed as undefined) | |
return x + y; | |
} | |
f(3) == 15 | |
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 | |
//--------------------------- Let + Const ------------------------------------ | |
function f() { | |
{ | |
let x; | |
{ | |
// okay, block scoped name | |
const x = "sneaky"; | |
//// error, const | |
//x = "foo"; | |
} | |
// okay, declared with `let` | |
x = "bar"; | |
//// error, already declared in block | |
//let x = "inner"; | |
} | |
} | |
//--------------------------- Iterators + For..Of ------------------------------------ | |
for (var x of["foo", "bar", "baz"]) { | |
console.log(x); | |
} | |
// output: | |
// foo | |
// bar | |
// baz | |
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 ------------------------------------ | |
let fibonacci2 = { | |
[Symbol.iterator]: function*() { | |
var pre = 0, cur = 1; | |
for (;;) { | |
var temp = pre; | |
pre = cur; | |
cur += temp; | |
yield cur; | |
} | |
} | |
} | |
for (var n of fibonacci2) { | |
// truncate the sequence at 1000 | |
if (n > 1000) | |
break; | |
console.log(n); | |
} | |
//--------------------------- Unicode ------------------------------------ | |
// same as ES5.1 | |
"𠮷".length == 2 | |
// new RegExp behaviour, opt-in ‘u’ | |
"𠮷".match(/./u)[0].length == 2 | |
// new form | |
"\u{20BB7}" == "𠮷" == "\uD842\uDFB7" | |
// new String ops | |
"𠮷".codePointAt(0) == 0x20BB7 | |
// for-of iterates code points | |
for(var c of "𠮷") { | |
console.log(c); | |
} | |
/*************************************************************** | |
* Features with incomplete support and polyfill-only features: * | |
****************************************************************/ | |
//--------------------------- Modules (Requires a Transpiler) ------------------------------------ | |
///Implicitly async model – no code executes until requested modules are available and processed. | |
/* | |
// lib/math.js | |
export function sum(x, y) { | |
return x + y; | |
} | |
export var pi = 3.141593; | |
// app.js | |
import * as math from "lib/math"; | |
console.log("2π = " + math.sum(math.pi, math.pi)); | |
// otherApp.js | |
import {sum, pi} from "lib/math"; | |
console.log("2π = " + sum(pi, pi)); | |
// lib/mathplusplus.js | |
export * from "lib/math"; | |
export var e = 2.71828182846; | |
export default function(x) { | |
return Math.exp(x); | |
} | |
// app.js | |
import exp, {pi, e} from "lib/mathplusplus"; | |
console.log("e^π = " + exp(pi)); | |
*/ | |
//--------------------------- Module Loaders (Not part of ES2015, Babel polyfill required) ------------------------------------ | |
/* | |
// Dynamic loading – ‘System’ is default loader | |
System.import("lib/math").then(function(m) { | |
alert("2π = " + m.sum(m.pi, m.pi)); | |
}); | |
// Create execution sandboxes – new Loaders | |
var loader = new Loader({ | |
global: fixup(window) // replace ‘console.log’ | |
}); | |
loader.eval("console.log(\"hello world!\");"); | |
// Directly manipulate module cache | |
System.get("jquery"); | |
System.set("jquery", Module({$: $})); // WARNING: not yet finalized | |
*/ | |
//--------------------------- Map + Set + WeakMap + WeakSet (Support via polyfill) ------------------------------------ | |
// 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; | |
// Weak Maps | |
var wm = new WeakMap(); | |
wm.set(s, { extra: 42 }); | |
wm.size === undefined | |
// Weak Sets | |
var ws = new WeakSet(); | |
ws.add({ data: 42 }); | |
// Because the added object has no other references, it will not be held in the set | |
//--------------------------- Proxies (Unsupported feature in most browsers) ------------------------------------ | |
// Proxying a normal object | |
var target = {}; | |
var handler = { | |
get: function (receiver, name) { | |
return `Hello, ${name}!`; | |
} | |
}; | |
var p = new Proxy(target, handler); | |
p.world === "Hello, world!"; | |
// Proxying a function object | |
var target = function () { return "I am the target"; }; | |
var handler = { | |
apply: function (receiver, ...args) { | |
return "I am the proxy"; | |
} | |
}; | |
var p = new Proxy(target, handler); | |
p() === "I am the proxy"; | |
//There are traps available for all of the runtime-level meta-operations: | |
/* | |
var handler = | |
{ | |
// target.prop | |
get: ..., | |
// target.prop = value | |
set: ..., | |
// 'prop' in target | |
has: ..., | |
// delete target.prop | |
deleteProperty: ..., | |
// target(...args) | |
apply: ..., | |
// new target(...args) | |
construct: ..., | |
// Object.getOwnPropertyDescriptor(target, 'prop') | |
getOwnPropertyDescriptor: ..., | |
// Object.defineProperty(target, 'prop', descriptor) | |
defineProperty: ..., | |
// Object.getPrototypeOf(target), Reflect.getPrototypeOf(target), | |
// target.__proto__, object.isPrototypeOf(target), object instanceof target | |
getPrototypeOf: ..., | |
// Object.setPrototypeOf(target), Reflect.setPrototypeOf(target) | |
setPrototypeOf: ..., | |
// for (let i in target) {} | |
enumerate: ..., | |
// Object.keys(target) | |
ownKeys: ..., | |
// Object.preventExtensions(target) | |
preventExtensions: ..., | |
// Object.isExtensible(target) | |
isExtensible :... | |
} */ | |
//--------------------------- Symbols (Limited support via polyfill) ------------------------------------ | |
(function() { | |
// module scoped symbol | |
var key = Symbol("key"); | |
function MyClass(privateData) { | |
this[key] = privateData; | |
} | |
MyClass.prototype = { | |
doStuff: function() { | |
//... this[key] ... | |
} | |
}; | |
// Limited support from Babel, full support requires native implementation. | |
typeof key === "symbol" | |
})(); | |
var c = new MyClass("hello") | |
c["key"] === undefined | |
//--------------------------- Subclassable Built-ins (Partial support) ------------------------------------ | |
// User code of Array subclass | |
class MyArray extends Array { | |
constructor(...args) { super(...args); } | |
} | |
var arr = new MyArray(); | |
arr[1] = 12; | |
arr.length == 2 | |
//--------------------------- Math + Number + String + Object APIs (Limited support from polyfill) ------------------------------------ | |
Number.EPSILON | |
Number.isInteger(Infinity) // false | |
Number.isNaN("NaN") // false | |
Math.acosh(3) // 1.762747174039086 | |
Math.hypot(3, 4) // 5 | |
Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2) // 2 | |
"abcde".includes("cd") // true | |
"abc".repeat(3) // "abcabcabc" | |
Array.from(document.querySelectorAll("*")) // Returns a real Array | |
Array.of(1, 2, 3) // Similar to new Array(...), but without special one-arg behavior | |
[0, 0, 0].fill(7, 1) // [0,7,7] | |
[1,2,3].findIndex(x => x == 2) // 1 | |
["a", "b", "c"].entries() // iterator [0, "a"], [1,"b"], [2,"c"] | |
["a", "b", "c"].keys() // iterator 0, 1, 2 | |
["a", "b", "c"].values() // iterator "a", "b", "c" | |
Object.assign(Point, { origin: new Point(0,0) }) | |
//--------------------------- Binary and Octal Literals (Babel only supports literal form) ------------------------------------ | |
0b111110111 === 503 // true | |
0o767 === 503 // true | |
//Only supports literal form: Babel is only able to transform 0o767 and not Number("0o767") | |
//--------------------------- Promises (Support via polyfill) ------------------------------------ | |
function timeout(duration = 0) { | |
return new Promise((resolve, reject) => { | |
setTimeout(resolve, duration); | |
}) | |
} | |
var p = timeout(1000).then(() => { | |
return timeout(2000); | |
}).then(() => { | |
throw new Error("hmm"); | |
}).catch(err => { | |
return Promise.all([timeout(100), timeout(200)]); | |
}) | |
//--------------------------- Reflect API (Support via polyfill) ------------------------------------ | |
var O = {a: 1}; | |
Object.defineProperty(O, 'b', {value: 2}); | |
O[Symbol('c')] = 3; | |
Reflect.ownKeys(O); // ['a', 'b', Symbol(c)] | |
function C(a, b){ | |
this.c = a + b; | |
} | |
var instance = Reflect.construct(C, [20, 22]); | |
instance.c; // 42 | |
//--------------------------- Tail Calls (Temporarily Removed from Babel) ------------------------------------ | |
function factorial3(n, acc = 1) { | |
"use strict"; | |
if (n <= 1) return acc; | |
return factorial3(n - 1, n * acc); | |
} | |
//// Stack overflow in most implementations today, | |
//// but safe on arbitrary inputs in ES2015 | |
//factorial3(100000) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment