Skip to content

Instantly share code, notes, and snippets.

@pyadav
Last active August 29, 2015 14:27
Show Gist options
  • Save pyadav/1378d3414eaf244c3566 to your computer and use it in GitHub Desktop.
Save pyadav/1378d3414eaf244c3566 to your computer and use it in GitHub Desktop.
Ecmascript features list
ES2015 (a.k.a. ES6)
- Lots of new language features
- Classes
- Arrow Functions
- Destructuring
- Let + Const
- Iterators
- Generators
- Modules
- Unicode support
- Much more!
- "Doesn't look like JavaScript"
Babel
- The one library you'll need to develop modern JavaScript™
- Has the best support for next generation JavaScript
- Most importantly, it's very easy to use
- Server side executable via babel-node
- Client side transformations
- Shared runtime
- Shared configuration via .babelrc
- Source map support
- JSX Support & Optimizations
- Plugins
Modules
import React from "react";
// var React = require("react");
import {serverPort} from "./appConfig";
// var serverPort = require("./appConfig").serverPort;
export default {};
// module.exports = {};
export default class {};
export default class extends React.Component {};
export default new class {};
Classes
class BaseAction {
dispatch() {
// do stuff
}
}
class SomeAction extends BaseAction {
constructor() {
super();
this.dispatch();
}
}
Generators
- "Generators are functions which can be exited
and later re-entered. Their context
(variable bindings) will be saved across
re-entrances."
~ MDN
- A way to control flow of a function.
Pause, resume, return, and throw.
- Can aide in the use of async operations
without resorting to callbacks
- async/await
- Iterators
- for ... of
- https://github.com/getify/You-Dont-Know-JS/blob/master/async%20&%20performance/ch4.md
io.js
- "Bringing ES6 to the Node Community!"
- Natively runs ES2015 code without any additional flags
- (With limited support. See above compatibility table)
- Can natively run Koa.js generators and promises
- Node 0.12 can run generators and promises natively too
- Requires the --harmony flag
React
- Describe your HTML in JavaScript
- React will figure out what to render from that
- Can render your HTML to a Static Markup
- React.renderToStaticMarkup(<Component />);
- We're able to use React Components as server side
templates
- Reuse developer skillsets on server and client
WebPack
- Transform and inline modules into static assets
- JavaScript
- CSS
- Images
- Define the transformations on modules using loaders
- babel-loader
- jsx-loader
- less-loader
- Can optimize for number of web requests,
payload size, etc.
- Define code split points and WebPack will form
async loaded chunks depending on your
optimization strategy
- Hot Module Reloading
- Will replace your module inline
- No page refresh
- Extensible via Plugins
Developing with WebPack
- Depending on your WebPack configuration, you likely
have a hash of each chunk included in the filename
- Something like main.09234919823fe8ac.js
- Good for long term caching purposes
- On a module change, WebPack will recompile the
chunks which will then have a different hash and
therefore a different filename
- This new filename needs to be communicated to our
React templates in order to serve the appropriate asset
- How could we accomplish this?
Flux
- Unidirectional data flow pattern
- Actions -> Dispatcher -> Stores -> Components -> Actions
- My talk at FITC Spotlight: Front-End
on different Front-End Paradigms
https://www.youtube.com/watch?v=mdHErrj2iV0
- Maybe we can use Flux to update our WebPack
entrypoint URL?
// One liner
var nums = evens.map((v, i) => v + i);
// Longer
nums.forEach(v => {
if (v % 5 === 0)
fives.push(v);
});
// Set up our async runners...
let doSomething = () => {
return new Promise((resolve,reject) => {
console.log('I like this...')
setTimeout(() => resolve('hi'), 1000);
});
},
appendSomething = (result1) => {
return new Promise((resolve,reject) => {
console.log('well maybe..')
setTimeout(() => resolve(result1 + ' hey there'), 1000);
});
}
// Plain promises...
doSomething()
.then(appendSomething)
.then((result) => {
console.log(result);
});
// ES7
async () => {
let result = await doSomething(),
result2 = await appendSomething(result);
console.log(result2)
}();
/*
ES7
```
async function f() {
await ...
}
```
ES6
```
const f = async(function* () {
yield ...
});
```
*/
function async(f) {
return function () {
let generator = f.apply(this, arguments);
return new Promise((resolve, reject) => {
let onValue = generator.next.bind(generator);
let onError = generator.throw.bind(generator);
(function step(callback) {
let next;
try {
next = callback();
} catch (err) {
return reject(err);
}
if (next.done) resolve(next.value);
else if (next.value && next.value.then) Promise.resolve(next.value)
.then((value) => step(() => onValue(value)), (err) => step(() => onError(err)));
else step(() => onValue(value));
}(onValue));
});
};
}
class name {
constructor(name){
this.name = name;
this.test = "test";
}
render(){
console.log(this.name);
}
}
//var tete = new name('arnaud');
//tete.render(); // return arnaud
class pseudo extends name{
constructor(name){
super(name);
this._pseudo = 'le nul';
}
get pseudo(){ // return pseudo
return this._pseudo;
}
set pseudo(val){ // Set the new value to pseudo
this._pseudo = val;
}
surname(){
//console.log(this); // return titi {name: "arnaud", test: "test", _pseudo: "le meilleur"}
console.log(this.name + ' ' + this.pseudo);
}
}
var tutu = new pseudo("arnaud");
tutu.surname(); // return "arnaud le nul"
tutu.pseudo = "le meilleur";
tutu.surname(); // return "arnaud le meilleur"
//Tested here : http://bit.ly/1LlRNy0
// list matching
var [a, , b] = [1,2,3];
// object matching shorthand
var {op, lhs, rhs} = getASTNode()
// Splat
function f(x, ...y) {
// y is an Array
return x * y.length;
}
f(3, "hello", true) == 6
// Spread
function f(x, y, z) {
return x + y + z;
}
// Pass each elem of array as argument
f(...[1,2,3]) == 6
const shapeType = {
triangle: new Symbol()
};
// Demo func
function getArea(shape, options) {
var area = 0;
switch (shape) {
case shapeType.triangle:
area = .5 * options.w * options.h;
break;
}
return area;
}
getArea(shapeType.triangle, {w: 100, h: 50});
function get(url) {
return new Promise(function(resolve, reject) {
var req = new XMLHttpRequest();
req.open('GET', url);
req.setRequestHeader('User-Agent', 'mralexgray');
req.onload = function() {
if (req.status == 200) {
resolve(JSON.parse(req.response));
}
else {
reject(Error(req.statusText));
}
};
req.onerror = function() {
reject(Error("Network Error"));
};
req.send();
});
}
var params = '?client_id=5d55f8b2c81b86fc413c&client_secret=f816768d68ca421eef677743218db6e768bc93f6';
//ES7 async/await
(async function() {
let res = await get('https://api.github.com/users/mralexgray/repos' +params)
let res2 = await get('https://api.github.com/users/alyssaq/repos' +params)
alert('ES7: ' + res[0].full_name + ',\n' + res2[0].full_name)
try {
let res2 = await get('https://api.github.com/rubbish' +params)
//alert('ES7 GOOD: ' + err)
} catch (err) {
alert('ES7 BAD: ' + err)
}
}());
//ES6 Promises
get('https://api.github.com/users/mralexgray/repos' +params).then(function (res) {
get('https://api.github.com/users/alyssaq/repos' +params).then(function (res2) {
//alert('ES6: ' + res[0].full_name + ',\n'+ res2[0].full_name)
get('https://api.github.com/rubbish' +params).then(function (res3) {
//alert('ES6 GOOD: ' + err)
}).catch(function (err){
//alert('ES6 BAD: ' + err)
})
})
})
// array utils
// =================================================================================================
const combine = (...arrays) => [].concat(...arrays);
// combine(["foo"], ["bar", "baz"], [1, 2]) // => ["foo", "bar", "baz", 1, 2]
const compact = arr => arr.filter(Boolean);
// compact([0, 1, false, 2, "", 3]) // => [1, 2, 3]
const contains = (() => Array.prototype.includes
? (arr, value) => arr.includes(value)
: (arr, value) => arr.some(el => el === value)
)();
// contains([1, 2, 3], 3) // => true
const difference = (arr, ...others) => {
var combined = [].concat(...others)
return arr.filter(el => !combined.some(exclude => el === exclude))
};
// difference([1, 2, 3, 4, 5], [5, 2, 10]) // => [1, 3, 4]
const head = arr => arr[0];
// head(["foo", "bar"]) // => "foo"
const initial = arr => arr.slice(0, -1);
// initial([3, 2, 1]) // => [3, 2]
const intersection = (...arrays) =>
[...Set([].concat(...arrays))].filter(toFind =>
arrays.every(arr => arr.some(el => el === toFind))
);
// intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]) // => [1, 2]
const last = arr => arr.slice(-1)[0];
// last(["foo", "bar"]) // => "bar"
const sortedIndex = (arr, value) =>
[value].concat(arr).sort().indexOf(value);
// sortedIndex([10, 20, 30, 40, 50], 35) // => 3
const tail = arr => arr.slice(1);
// tail(["foo", "bar", "baz"]) // => ["bar", "baz"
const toArray = (() => Array.from ? Array.from : obj => [].slice.call(obj))();
// Array.isArray((() => toArray(arguments))("foo", "bar")) // => true
const union = (...arrays) => [...Set([].concat(...arrays))];
// union([1, 2, 3], [101, 2, 1, 10], [2, 1]) // => [1, 2, 3, 101, 10]
const unique = arr => [...Set(arr)];
// unique([1, 2, 1, 3, 1, 4]) // => [1, 2, 3, 4]
const without = (arr, ...values) =>
arr.filter(el => !values.some(exclude => el === exclude));
// object utils
// =================================================================================================
const getValues = obj => Object.keys(obj).map(key => obj[key]);
const merge = (() => {
const extend = Object.assign ? Object.assign : (target, ...sources) => {
sources.forEach(source =>
Object.keys(source).forEach(prop => target[prop] = source[prop])
);
return target;
};
return (...objects) => extend({}, ...objects);
})();
const toMap = (() => {
const convert = obj => new Map(Object.keys(obj).map(key => [key, obj[key]]));
return obj => obj instanceof Map ? obj : convert(obj);
})();
// toMap({ name: "Ben", age: 31 }); // => Map { name: "Ben", age: 31 }
// math
// =================================================================================================
const min = arr => Math.min(...arr);
// min([10, 50, 30]) // => 10
const max = arr => Math.max(...arr);
// max([10, 50, 30]) // => 50
const sum = arr => arr.reduce((a, b) => a + b);
// sum([1, 2, 3]) // => 6
const product = arr => arr.reduce((a, b) => a * b);
// product([2, 5, 10]) // => 100
// function decorators
// =================================================================================================
const not = fn => (...args) => !fn(...args);
// const isNull = x => x == null;
// const isSet = not(isNull);
// isSet(undefined); // => false
const maybe = fn =>
(...args) => {
if (args.length < fn.length || args.some(arg => arg == null)) return;
return fn(...args);
};
// var greet = (message, name) => console.log(message + " " + name);
// var safeGreet = requireArguments(greet);
// greet("Hi"); // => "Hi undefined"
// safeGreet("Hi"); // => Doesn't execute
const once = fn => {
var done = false;
return (...args) => {
if (done) return;
done = true;
fn(...args);
};
};
// const greet = () => console.log("Hi");
// const greetOnce = once(greet);
// greetOnce(); // => "Hi"
// greetOnce(); // => Doesn't execute
const curry = fn => {
const arity = fn.length;
const curried = (...args) =>
args.length < arity ? (...more) => curried(...args, ...more) : fn(...args);
return curried;
};
// const add = curry((a, b) => a + b);
// add(2, 3); // => 5
// add(2)(3); // => 5
const pipeline = (...funcs) =>
value => funcs.reduce((a, b) => b(a), value);
// var plus1 = a => a + 1;
// var mult2 = a => a * 2;
// var addThenMult = pipeline(plus1, mult2);
// addThenMult(5); // => 12
// See http://www.2ality.com/2014/09/es6-modules-final.html
// There are two ways in which you can export things that
// are inside the current module:
// >>> 1. Mark declarations with the export keyword
export let myVar = 'some text';
export const MY_CONST = 42;
export class MyClass { }
export function myFunc() { }
export function* myGeneratorFunc() { }
// Note the "operand" of a default export is an expression
// (including function expressions and class expressions)
export default 123;
export default x => x;
export default function (x) { return x; };
export default class {
constructor(x, y) {
this.x = x;
this.y = y;
}
};
// >>> 2. List everything you want to export at the end of the module
const MY_CONST = 'HI';
function myFunc() { }
export { MY_CONST, myFunc };
// You can also export things under different names
export { MY_CONST as THE_CONST, myFunc as theFunc };
// Re-exporting means adding another module’s exports
// to those of the current module
export * from 'src/other_module';
export { foo, bar } from 'src/other_module';
export { foo as myFoo, bar } from 'src/other_module';
// See http://www.2ality.com/2014/09/es6-modules-final.html
// Default exports and named exports
import theDefault, { named1, named2 } from 'src/mylib';
import theDefault from 'src/mylib';
import { named1, named2 } from 'src/mylib';
// Renaming: import named1 as myNamed1
import { named1 as myNamed1, named2 } from 'src/mylib';
// Importing the module as an object
// (with one property per named export)
import * as mylib from 'src/mylib';
// Only load the module, don’t import anything
import 'src/mylib';
// When using module name mapping e.g. JSPM
import $ from 'jquery';
import _ from 'lodash';
// So we define a function that loads images, and returns a promise for us to listen to
function loadImages(images){
//alert(blah); //promise should catch on this error here
// We can take advantage of `map` which iterates through an array and makes an array
// out of the returns of each iteration. In this case, we return a promise for each
// url, for `Promise.all` to listen to later.
var promises = images.map(function(url){
// Create a Deferred object and image, and handle the resolution stuff.
var deferred = Promise.defer();
var image = new Image();
image.onload = function(){deferred.resolve('image success: '+ url);};
image.onerror = function(){deferred.reject('image failed: ' + url);};
image.onabort = function(){deferred.reject('image aborted: ' + url);};
image.src = url;
// Return the promise, which will be stored in the array, thanks to `map`
return deferred.promise;
});
// Listen on the array of promises (aha moment: jQuery.when == Promises.all, more or less.)
return Promise.all(promises);
}
// Now we use `loadImages`, loading an array of urls, and listening for notices
loadImages([
'http://www.mozilla.org/media/img/firefox/favicon.png',
'https://developer.cdn.mozilla.net/media/redesign/img/favicon32.png'
]).then(function(value){
console.log('loadImages successful: ' + value);
},function(error){
console.log('loadImages failed: ' + error);
});
// With comments:
function promiseSome(promises) {
// We're going to 'sort' promises into fulfilled & rejected values
var fulfills = [];
var rejects = [];
// Using reduce to create a promise chain
return promises.reduce(function(chain, promise) {
// Wait for the last in the chain
return chain.then(function() {
// Wait for the current in the chain.
// This has a nice side effect that it deals with values
// in `promises` that are simple values rather than promises
return promise;
}).then(function(val) {
// Store the success value
fulfills.push(val);
}, function(err) {
// Store the failure
// This also 'handles' the error in terms of the chain,
// so the chain always fulfills with undefined
rejects.push(err);
});
}, Promise.resolve()).then(function() {
// Reject only if nothing fulfilled
if (!fulfills[0]) throw Error("All failed");
return fulfills;
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment