ES6 ~ ES2015
TypeScirpt
May '95
Dec '95
Sep '95
1997
Aug '96
1999
1998
2009
2003
2015
2011
2016
Mocha (Brendan Eich, Netscape)
LiveScript
JavaScript
Edition 1
JScript (Microsoft)
Edition 2
Edition 3
Edition 4
Edition 5
Edition 5.1
Edition 6
Edition 7
ECMA-262 specification
/*jshint esnext: true */
import Todo from './todo';
import {values} from './generators';
class TodoList {
constructor() {
this.todos = {};
this.length = 0;
}
add(text, done = false) {
let todo = new Todo(text, done);
this.todos[String(todo.timestamp)] = todo;
this.length++;
}
archiveCompleted() {
for (let todo of values(this.todos)) {
if (todo.done) this.delete(todo);
}
}
delete(todo) {
delete this.todos[String(todo.timestamp)];
this.length--;
}
getUncompletedCount() {
let count = 0;
for (let todo of values(this.todos)) {
if (!todo.done) count++;
}
return count;
}
}
export default TodoList;
/*jshint esnext: true */
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
var _todo = require('./todo');
var _todo2 = _interopRequireDefault(_todo);
var _generators = require('./generators');
var TodoList = (function () {
function TodoList() {
_classCallCheck(this, TodoList);
this.todos = {};
this.length = 0;
}
_createClass(TodoList, [{
key: 'add',
value: function add(text) {
var done = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1];
var todo = new _todo2['default'](text, done);
this.todos[String(todo.timestamp)] = todo;
this.length++;
}
}, {
key: 'archiveCompleted',
value: function archiveCompleted() {
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = (0, _generators.values)(this.todos)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var todo = _step.value;
if (todo.done) this['delete'](todo);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator['return']) {
_iterator['return']();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
}
}, {
key: 'delete',
value: function _delete(todo) {
delete this.todos[String(todo.timestamp)];
this.length--;
}
}, {
key: 'getUncompletedCount',
value: function getUncompletedCount() {
var count = 0;
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = (0, _generators.values)(this.todos)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var todo = _step2.value;
if (!todo.done) count++;
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2['return']) {
_iterator2['return']();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
return count;
}
}]);
return TodoList;
})();
exports['default'] = TodoList;
module.exports = exports['default'];
ES5
ES6
/*jshint esnext: true */
import Todo from './todo';
import {values} from './generators';
class TodoList {
constructor() {
this.todos = {};
this.length = 0;
}
add(text, done = false) {
let todo = new Todo(text, done);
this.todos[String(todo.timestamp)] = todo;
this.length++;
}
archiveCompleted() {
for (let todo of values(this.todos)) {
if (todo.done) this.delete(todo);
}
}
delete(todo) {
delete this.todos[String(todo.timestamp)];
this.length--;
}
getUncompletedCount() {
let count = 0;
for (let todo of values(this.todos)) {
if (!todo.done) count++;
}
return count;
}
}
export default TodoList;
$traceurRuntime.registerModule("todoservice.js", [], function() {
"use strict";
var __moduleName = "todoservice.js";
var Todo = $traceurRuntime.getModule($traceurRuntime.normalizeModuleName("./todo", "todoservice.js")).default;
var values = $traceurRuntime.getModule($traceurRuntime.normalizeModuleName("./generators", "todoservice.js")).values;
var TodoList = function() {
function TodoList() {
this.todos = {};
this.length = 0;
}
return ($traceurRuntime.createClass)(TodoList, {
add: function(text) {
var done = arguments[1] !== (void 0) ? arguments[1] : false;
var todo = new Todo(text, done);
this.todos[String(todo.timestamp)] = todo;
this.length++;
},
archiveCompleted: function() {
var $__7 = true;
var $__8 = false;
var $__9 = undefined;
try {
for (var $__5 = void 0,
$__4 = (values(this.todos))[Symbol.iterator](); !($__7 = ($__5 = $__4.next()).done); $__7 = true) {
var todo = $__5.value;
{
if (todo.done)
this.delete(todo);
}
}
} catch ($__10) {
$__8 = true;
$__9 = $__10;
} finally {
try {
if (!$__7 && $__4.return != null) {
$__4.return();
}
} finally {
if ($__8) {
throw $__9;
}
}
}
},
delete: function(todo) {
delete this.todos[String(todo.timestamp)];
this.length--;
},
getUncompletedCount: function() {
var count = 0;
var $__7 = true;
var $__8 = false;
var $__9 = undefined;
try {
for (var $__5 = void 0,
$__4 = (values(this.todos))[Symbol.iterator](); !($__7 = ($__5 = $__4.next()).done); $__7 = true) {
var todo = $__5.value;
{
if (!todo.done)
count++;
}
}
} catch ($__10) {
$__8 = true;
$__9 = $__10;
} finally {
try {
if (!$__7 && $__4.return != null) {
$__4.return();
}
} finally {
if ($__8) {
throw $__9;
}
}
}
return count;
}
}, {});
}();
var $__default = TodoList;
return {get default() {
return $__default;
}};
});
$traceurRuntime.getModule("todoservice.js" + '');
ES5
ES6
// Todo Model
// ----------
// Our basic **Todo** model has `content`, `order`, and `done` attributes.
class Todo extends Backbone.Model {
// Default attributes for the todo.
defaults() {
return {
content: "empty todo...",
done: false
}
}
// Ensure that each todo created has `content`.
initialize() {
if (!this.get("content")) {
this.set({ "content": this.defaults().content });
}
}
// Toggle the `done` state of this todo item.
toggle() {
this.save({ done: !this.get("done") });
}
// Remove this Todo from *localStorage* and delete its view.
clear() {
this.destroy();
}
}
// Todo Model
// ----------
// Our basic **Todo** model has `content`, `order`, and `done` attributes.
var Todo = (function (_super) {
__extends(Todo, _super);
function Todo() {
_super.apply(this, arguments);
}
// Default attributes for the todo.
Todo.prototype.defaults = function () {
return {
content: "empty todo...",
done: false
};
};
// Ensure that each todo created has `content`.
Todo.prototype.initialize = function () {
if (!this.get("content")) {
this.set({ "content": this.defaults().content });
}
};
// Toggle the `done` state of this todo item.
Todo.prototype.toggle = function () {
this.save({ done: !this.get("done") });
};
// Remove this Todo from *localStorage* and delete its view.
Todo.prototype.clear = function () {
this.destroy();
};
return Todo;
}(Backbone.Model));
ES5
ES6
function Client (firstname, lastname) {
this.id = undefined
this.firstname = firstname
this.lastname = lastname
}
Client.prototype.getFullName = function () {
return this.firstname + this.lastname;
}
Client.prototype.setId = function () {
this.id = generateGuid();
}
var Client = new Client()
client.getFullName()
client.setId()
ES5
ES5
ES5
var foo = {};
foo.someMethod = function(){
alert(this);
}
var foo = function(){
alert(this);
}
foo();
foo.someOtherMethod = function (){
var that=this;
function bar(){
alert(that);
}
}
function Foo(){
this.confusing = 'hell yeah';
}
var myObject = new Foo();
var foo = {};
foo.someMethod = function(){ console.log(this.toString()); }
foo.someMethod() // [object Object]
foo.someMethod.apply (foo, []) // [object Object]
foo.someMethod.apply ("foo", []) // foo
class Client {
constructor(firstname, lastname) {
this.id = undefined
this.firstname = firstname
this.lastname = lastname
}
getFullName() {
return this.firstname + this.lastname
}
generateId() {
this.id = generateGuid()
}
}
function Client (firstname, lastname) {
this.id = undefined
this.firstname = firstname
this.lastname = lastname
}
Client.prototype.getFullName = function () {
return this.firstname + this.lastname
}
Client.prototype.setId = function () {
this.id = generateGuid()
}
ES6
ES5
class Client {
constructor(firstname, lastname) {
this.id = undefined
this.firstname = firstname
this.lastname = lastname
}
getFullName() {
return this.firstname + this.lastname
}
generateId() {
this.id = generateGuid()
}
}
ES6
class Client {
constructor(firstname, lastname) {
this.id = undefined
this.firstname = firstname
this.lastname = lastname
}
getFullName() {
return this.firstname + this.lastname
}
generateId() {
this.id = generateGuid()
}
static generateGuid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1)
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4()
}
}
ES6
function Client (firstname, lastname) {
this.id = undefined
this.firstname = firstname
this.lastname = lastname
}
var TCSClient = Object.create(Client)
TCSClient.evalSystem = "TCS"
TCSClient.firstname = "Joe Bloggs"
ES5
ES5
class TCSClient extends Client {
this.evalSystem = "TCS"
}
var TCSClient = Object.create(Client);
TCSClient.evalSystem = "TCS"
ES5
ES6
class TCSClient extends Client {
getFullName() {
return this.firstname + " " +
this.lastname
}
}
var TCSClient = Object.create(Client)
TCSClient.prototype.getFullName() {
return this.firstname + " " +
this.lastname
}
ES5
ES6
class DRClient extends Client {
this.vcNumberPrefix = "W"
generateVCNumber() {
super.generateVCNumber()
}
}
var TCSClient = Object.create(Client)
TCSClient.vcNumberPrefix = "A"
TCSClient.prototype.generateVCNumber = function() {
Client.prototype.generateVCNumber.call(this)
}
ES5
ES6
function Client () {
this.vcNumber = undefined
this.vcNumberPrefix = ""
}
Client.prototype.generateVCNumber = function () {
var number = Math.floor(Math.random() * 10000000)
this.vcNumber = this.vcNumberPrefix + pad(number, 7)
}
ES5
// someModule.js
function doSomething () {
console.log("foo");
}
exports.doSomething = doSomething;
//otherModule.js
var someModule = require('someModule');
someModule.doSomething();
// someModule.js
define(["lib"], function (lib) {
function doSomething() {
console.log("foo");
}
return {
doSomething: doSomething
}
});
//otherModule.js
require(["someModule"], function(someModule){
someModule.doSomething();
});
// ClientService.js
class ClientService {
clients = [];
addClient(client) {
this.clients.add(client);
}
}
export default ClientService;
import ClientService from './ClientService';
class ClientComponent {
submitClient(client) {
ClientService.addClient(client);
}
}
ES6
ES6
Default exports
//------ MyClass.js ------
class MyClass { ... };
export default MyClass;
//------MyFunction.js ----
function myFunction() { ... };
export default myFunction;
//------ lib.js ------
export const sqrt = Math.sqrt;
export function square(x) {
return x * x;
}
export function diag(x, y) {
return sqrt(square(x) + square(y));
}
Named exports
// ----- main.js ---
import * as lib from './lib';
console.log(lib.square(11)); // 121
console.log(lib.diag(4, 3)); // 5
// ----- main.js ---
import MyClass from './MyClass'
import thatFunction from './myFunction'
var my = new MyClass();
var res = thatFunction();
// ClientService.js
class ClientService {
clients = [];
addClient(client) {
this.clients.add(client);
}
}
export default ClientService;
ES6
import ClientService from './ClientService';
ES6
import MyService from './ClientService';
class ClientComponent {
submitClient(client) {
MyService.addClient(client);
}
}
module.exports = ClientService;
CommonJS
export default ClientService;
ES6
var Service = require('./ClientService');
import Service from ('./ClientService');
function foo() {
module.exports = 'bar'; // OK
}
CommonJS
function foo() {
export default 'bar'; // Syntax error
}
ES6
// Constants.js
var $BANKRUPTCY_MIN_DEBT = 1001;
var $SEQUESTRATION_MIN_DEBT = 3000;
export $BANKRUPTCY_MIN_DEBT;
export $SEQUESTRATION_MIN_DEBT;
ES6
// Constants.js
var $BANKRUPTCY_MIN_DEBT = 1001;
var $SEQUESTRATION_MIN_DEBT = 3000;
export { $BANKRUPTCY_MIN_DEBT,
$SEQUESTRATION_MIN_DEBT}
ES6
ES6
ES6
import {$BANKRUPTCY_MIN_DEBT,
$SEQUESTRATION_MIN_DEBT} from './Constants';
function isEligibleForBankruptcySequestration(
isScottish, debtTotal) {
var minDebt;
if(isScottish) { minDebt = $SEQUESTRATION_MIN_DEBT }
else { minDebt = $BANKRUPTCY_MIN_DEBT };
return debtTotal >= minDebt;
}
// Constants.js
var $BANKRUPTCY_MIN_DEBT = 1001;
var $SEQUESTRATION_MIN_DEBT = 3000;
export $BANKRUPTCY_MIN_DEBT;
export $SEQUESTRATION_MIN_DEBT;
ES6
ES6
import {$BANKRUPTCY_MIN_DEBT as minBank,
$SEQUESTRATION_MIN_DEBT as minSeq
} from './Constants';
function isEligibleForBankruptcySequestration(
isScottish, debtTotal) {
var minDebt;
if(isScottish) { minDebt = minSeq }
else { minDebt = minBank };
return debtTotal >= minDebt;
}
// Constants.js
var $BANKRUPTCY_MIN_DEBT = 1001;
var $SEQUESTRATION_MIN_DEBT = 3000;
export $BANKRUPTCY_MIN_DEBT;
export $SEQUESTRATION_MIN_DEBT;
ES6
ES6
import * as incomes from './IncomesController'
function submitIncomes() {
var valIncomeSupport = incomes.incomeSupport;
var valJobseekers = incomes.jobseekers ;
var valIncapacity = incomes.incapacity ;
var valTotalBenefitIncome = incomes.totalBenefitIncome();
}
// IncomesController.js
export var incomeSupport;
export var jobSeekers;
export var incapacity;
export var totalBenefitIncome = function() {
incomeSupport +
jobSeekers +
incapacity;
}
//------ lib.js ------
export let mutableValue = 3;
export function incMutableValue() {
mutableValue++;
}
//------ main.js ------
import * as lib from './lib';
// The imported value is live
console.log(lib.mutableValue); // 3
lib.incMutableValue();
console.log(lib.mutableValue); // 4
// The imported value can’t be changed
lib.mutableValue++; // TypeError
ES6
ES6
var mySymbol = Symbol("description");
console.log(typeof mySymbol); // 'symbol'
ES6
Symbol('foo') === Symbol('foo'); // false
ES6
var symbol = new Symbol(); // TypeError
ES6
if (element.isMoving) {
smoothAnimations(element);
}
element.isMoving = true;
var isMoving = Symbol("isMoving");
...
if (element[isMoving]) {
smoothAnimations(element);
}
element[isMoving] = true;
ES6
var myArray = ['a', 'b', 'c'];
var myIterable = myArray[Symbol.iterator]();
> iterable.next()
{ value: 'a', done: false };
> iterable.next()
{ value: 'b', done: false };
> iterable.next()
{ value: 'c', done: false };
> iterable.next()
{ value: undefined, done: true };
Symbol.for('foo') === Symbol.for('foo'); // true
Symbol.for(key)
Symbol.keyFor(symbol)
var mySymbol = Symbol.for('foo');
console.log(Symbol.keyFor(mySymbol)); // 'foo'
var iterable = {
next: function(){
returns {value: 1, done: true}
}
}
var foo = { [Symbol.iterator]: iterable }
foo[Symbol.iterator] = iterable
iterable.next() // returns {value: 1, done: true}
[Symbol.iterator]: () => ({
items: ['f', 'o', 'o'],
next: function () {
return {
done: this.items.length === 0,
value: this.items.shift()
}
}
})
ES6
next() method (no args)
returns Object with done, value
Adheres to iterator protocol
function* myGenerator() {}
// or
function *myGenerator() {}
ES6
function* myGenerator() {
yield 'f';
console.log('o');
yield 'o';
console.log('b');
yield 'a';
console.log('r');
}
var fooBar = myGenerator();
for(var item of fooBar) {
console.log(item); // 'f' 'o' 'o' 'b' 'a' 'r'
}
ES6
ES6
function *myGenerator(x) {
var y = x + 3;
var z = 1 + (yield(y));
return z;
}
ES6
var gen = myGenerator(2);
console.log( gen.next() );
console.log( gen.next(6) );
ES6
1 - myGenerator function instantiated with param x = 2
{ value: 5, done: false }
1
2
2 - next() called on generator function. No 'yield' expression encountered yet, so no param
3
3 - execution paused on yield expression; var y passed out as 5
4 - console logs
4
7
5 - execution resumes with yield expression as passed in param (6)
6
6 - since yield expression is 6, z becomes 7 (1 + 6)
7 - end of generator function; console logs
{ value: 7, done: true }
5
var foo = true;
function bar() {
if (!foo) {
var foo = "Foo is false!"
};
console.log(foo)
}
bar()
ES5
> Foo is false!
Console:
var foo;
function bar() {
var foo;
if (!foo) {
foo = "Foo is false!"
};
console.log(foo);
}
foo = true;
bar();
ES5
var x = 1;
if (x) {
var x = 2;
};
console.log(x);
> 2
Console:
ES5
var x = 1;
if (x) {
(function () {
var x = 2;
})
};
console.log(x);
> 1
Console:
ES5
var x = 1;
if (x) {
let x = 2;
}
console.log(x);
> 1
Console:
ES6
if (x) {
let foo;
let foo; // TypeError thrown.
}
function do_something() {
console.log(foo); // ReferenceError
let foo = 2;
}
for (let i = 0; i<10; i++) {
console.log(i); // 0, 1, 2, ... 9
}
console.log(i); // i is not defined
const IP = 3.14
const STUFF = { things: ['chair', 'desk', 'computer'] };
const FOO; // SyntaxError: missing = in const declaration
e.g.
const stuff = { things: ['chair', 'desk'] };
stuff = {}; // fails
console.log(stuff.things); // ...
e.g.
const stuff = { things: ['chair', 'desk', 'computer'] };
stuff.things.push('pot plant');
console.log(stuff.things);
// chair,desk,computer,pot plant
e.g.
function(param1, param2, ..., paramN) { statements }
// Equals to
(param1, param2, …, paramN) => { statements }
function(a) { return a * a }
// Equals to
a => a * a
() => { statements }
// Equals to
_ => { statements }
(param1, param2, …, paramN) => { return expression; }
// Equals to
(param1, param2, …, paramN) => expression
function Counter() {
var that = this;
that.seconds = 0;
setInterval(function() {
that.seconds++
}, 1000);
}
ES5
function Counter() {
this.seconds = 0;
setInterval(function() {
this.seconds++
}.bind(this), 1000);
}
ES5
function Counter() {
this.seconds = 0;
setInterval(function() {
this.seconds++
}.bind(this), 1000);
}
ES5
function Counter() {
this.seconds = 0;
setInterval(() => this.seconds++, 1000);
}
ES6
var hashMap = {};
function add(key, value) {
hashMap[key] = value;
}
function get(key) {
return hashMap[key];
}
add('request', { description: 'Simplified HTTP request client' });
add('moment', { description: 'Parse, validate, manipulate, and display dates' });
add('lodash', { description: 'The modern build of lodash modular utilities' });
var registry = {};
function add(element, meta) {
registry[element] = meta;
}
function get(element) {
return registry[element];
}
add(document.getElementById("wages-panel"), { display: true });
add(document.getElementById("child-income-panel"), { display: false });
add(document.getElementById("wages-panel"), { display: true });
var map = new Map();
map.set(new Date(), function today() {});
map.set(() => 'key', { foo: 'bar' });
map.set(Symbol('items'), [1, 2]);
var items = [
[new Date(), function today() {}],
[() => 'key', { foo: 'bar' }],
[(Symbol('items'), [1, 2])
]
// 2D key-value Array to map
var map = new Map(items);
map.get(Symbol('items')) // returns [1,2]
const privateData = new WeakMap();
class MyClass {
constructor (name, age) {
privateData(this, { name: name, age: age });
}
getName () {
return privateData.get(this).name;
}
getAge() {
return privateData.get(this).age;
}
}
let answersMap = new WeakMap();
let childBenefit = document.getElementById('child-benefit');
myElement.addEventListener('change', function() {
var answerFrequency = getFrequency();
answersMap.set(childBenefit, {frequency: answerFrequency}
}, false);
let childNumber = document.getElementById('child-number')
if(childNumber.number === 0) {
childBenefit.parentNode.removeChild(childBenefit)
}
console.log(answerMap.get(childBenefit) // undefined
var text = `
This is a template literal
'It can span multiple lines'
"And can contain quotation marks"
`
ES6
var text = (
'This is the old method\n' +
'for strings spanning\n' +
'several lines'
)
var text = [
'Or',
'perhaps',
'this'
].join('\n')
ES5
var text = `the time and date is ${today.toLocaleString()}`
// 'the time and date is 1/1/2016, 09:20:00 AM'
ES6
var a = 5;
var b = 10;
function tag(strings, ...values) {
console.log(strings[0]); // "Hello "
console.log(strings[1]); // " world "
console.log(values[0]); // 15
console.log(values[1]); // 50
return "Bazinga!";
}
tag`Hello ${ a + b } world ${ a * b }`;
// "Bazinga!"
@View({
template:`
<div *ng-if="userService.isAnyUsers()">
<div class="userlist-search">
<p><label>Search user:</label>
<input type="text" [(ng-model)]='searchTerm'></p>
</div>
</div>
`
})
Angular2
var myObject = { foo:'bar', baz: 'qux' }
ES5
var foo = { bar: 'bar' }
console.log(foo.bar) // 'bar'
ES5
var bar = 'bar';
var foo = { bar };
console.log(foo.bar); // 'bar'
ES6
var foo = {
bar(baz) { }
}
ES6
var foo = {
bar: function(baz) { }
}
ES5
var bar = 'bar'
var baz = { [bar]: 'qux' }
console.log(baz)
// { bar: 'qux' }
ES6
var foo = { ['bar' + 'baz']: 'qux' }
console.log(foo)
// { barbaz: 'qux' }
ES6
let myObject = { foo:'bar', baz: 'qux' }
ES6
let { foo, baz } = myObject
console.log(foo) // 'bar'
console.log(baz) // 'qux'
ES6
let myObject = { foo:'bar', baz: 'qux' }
let { norf: a } = myObject
console.log(a) // undefined
ES6
let { foo : f, baz : b } = myObject
console.log(f) // 'bar'
console.log(b) // 'qux'
ES6
let myObject = { foo: [{ bar: 'baz', qux: 'norf' }] }
let { foo: [{ bar: a }] } = myObject
console.log(a) // 'baz'
ES6
let myObject = { foo:'bar', baz: undefined }
let { baz = 'default' } = myObject
console.log(baz) // 'default'
ES6
let [, x, y] = [1, 2, 3]
console.log(x) // 2
console.log(y) // 3
ES6
let [x, y] = [1, 2, 3]
console.log(x) // 1
console.log(y) // 2
ES6
function displayNameAge ( {name, age} ) {
console.log(`${name} is ${age} years old`)
}
displayNameAge( { age: 27, name: 'John'} ) // 'John is 27 years old'
ES6
function random() ( {min=1, max=100} ) {
return Math.floor(Math.random() * (max - min) + min
}
console.log(random( {} )) // 67
console.log(random( { max: 20 } ) // 11
ES6
function getUrlParts(url) {
var regEx = /^(https?):\/\/(debtremedy.stepchange\.org)(\/page\/([a-z0-9-]+))$/
return regEx.exec(url)
}
var parts = getUrlParts('http://debtremedy.stepchange.org/page/benefitIncome')
var [,protocol,host,pathname,slug] = parts
console.log(protocol) // 'http'
console.log(host) // 'debtremedy.stepchange.org'
console.log(pathname) // '/page/YourIncome'
console.log(slug) // 'YourIncome'
ES6
// Function calls
myFunction(...iterable);
// Array literals
[...iterable, 4, 5, 6]
// Destructing
[a, b, ...iterable] = [1, 2, 3, 4, 5];
function concat() {
return Array.prototype.slide.call(arguments).join(' ')
}
var result = concat('Lorem', 'ipsum', 'dolor', 'sit', 'amet')
console.log(result) // 'Lorem ipsum dolor sit amet'
ES5
function concat(...words) {
return words.join(' ')
}
var result = concat('Lorem', 'ipsum', 'dolor', 'sit', 'amet')
console.log(result) // 'Lorem ipsum dolor sit amet'
ES6
function concat(prefix, suffix, ...words) {
return prefix + words.join(' ') + suffix
}
var result = concat('START', 'END', 'Lorem', 'ipsum', 'dolor', 'sit', 'amet')
console.log(result) // 'START Lorem ipsum dolor sit amet END'
ES6
ES5
function concat() {
var words = Array.prototype.slide.call(arguments);
var prefix = words.shift();
var suffix = words.shift();
return prefix + words.join(' ') + suffix;
}
var result = concat('START', 'END', 'Lorem', 'ipsum', 'dolor', 'sit', 'amet')
console.log(result) // 'START Lorem ipsum dolor sit amet END'
var missing = [4, 5, 6]
var sequence = [1, 2, 3, ...missing, 7, ,8 , 9]
ES6
new Promise(executor);
new Promise(function(resolve, reject) { ... });
var promise = new Promise(function(resolve, reject) {
// do something
if( /* thing was done */ ) {
resolve("Success");
}
else {
reject(Error("Failed"));
}
});
ES6
callback with 'resolve' and 'reject' params
promise.then(function(result) {
// Action on success
}, function(err) {
// Action on error
});
ES6
callback for success case
callback for failure case
function getData($timeout, $q) {
return function() {
var defer = $q.defer()
// async function
setTimeout(function() {
if (Math.round(Math.random())) {
defer.resolve('data received');
}
else {
defer.reject('error');
}
}, 1000);
return defer.promise
}
}
AngularJS
getJSON('faq.json').then(function(faq) {
return getJSON(faq.sectionUrl[0]);
}).then(function(section1) {
console.log('Section 1: ' + section1);
}
ES6
var p = new Proxy(target, handler);
target - object or function to wrap with Proxy.
handler - an object whose properties are functions which define the behavior of the proxy when an operation is performed on it.
var target = {}
var handler = {}
var proxy = new Proxy(target, handler)
proxy.a = 'b'
console.log(target.a) // <- 'b'
console.log(proxy.c === undefined) // <- true
var handler = {
get (target, key) {
console.info(`Get on property "${key}"`)
return target[key]
}
}
var target = {}
var proxy = new Proxy(target, handler)
proxy.a = 'b'
proxy.a // <- 'Get on property "a"'
proxy.b // <- 'Get on property "b"'
var handler = {
get (target, key) {
invariant(key, 'get')
return target[key]
},
set (target, key, value) {
invariant(key, 'set')
return true
}
}
function invariant (key, action) {
if (key[0] === '_') {
throw new Error(`Invalid attempt to ${action} private "${key}" property`)
}
}
var target = {}
var proxy = new Proxy(target, handler)\
proxy.a = 'b'
console.log(proxy.a) // <- 'b'
proxy._prop // <- Error: Invalid attempt to get private "_prop" property
proxy._prop = 'c' // <- Error: Invalid attempt to set private "_prop" property
var validator = {
set (target, key, value) {
if (key === 'age') {
if (typeof value !== 'number' || Number.isNaN(value)) {
throw new TypeError('Age must be a number')
}
if (value <= 0) {
throw new TypeError('Age must be a positive number')
}
}
return true
}
}
var person = { age: 27 }
var proxy = new Proxy(person, validator)
proxy.age = 'foo' // <- TypeError: Age must be a number
proxy.age = NaN // <- TypeError: Age must be a number
proxy.age = 0 // <- TypeError: Age must be a positive number
proxy.age = 28
console.log(person.age) // <- 28
var target = {}
var handler = {}
var {proxy, revoke} = Proxy.revocable(target, handler)
proxy.a = 'b'
console.log(proxy.a) // <- 'b'
revoke()
console.log(proxy.a) // <- TypeError: illegal operation attempted on a revoked proxy
var x:number = 1
var n = 1 // var n:number = 1
console.log(typeof(n)) // number
var s = "Hello World" // var s:string = "Hello World"
console.log(typeof(s)) // string
n = s; // error
s = n; // error
function f() {
return "hello"
}
console.log(typeof(f.call())) // string
TypeScript
window.onmousedown = function(mouseEvent) {
console.log(mouseEvent.buton); // <- Error
};
window.onmousedown = function(mouseEvent: any) {
console.log(mouseEvent.buton); // <- OK
};
TypeScript
var x = [0, 1, 2]; // number[]
var y = [0, '1', 2]; // any[]
var zoo = [new Rhino(), new Elephant(), new Snake()]; // Object[]
var zoo: Animal[] = [new Rhino(), new Elephant(), new Snake()]; // Animal[]
TypeScript
function add(num1, num2): number {
return num1 + num2;
}
function concat(str1, str2): string {
return str1 + str2;
}
function warnUser(): void {
alert("This function doesn't return a type");
}
function add(num1: number, num2: number) {
return num1 + num2;
}
function concat(str1: string, str2: string) {
return str1 + str2;
}
TypeScript
function buildName(firstName: string, lastName?: string) {
if (lastName)
return firstName + " " + lastName;
else
return firstName;
}
var result1 = buildName("Bob"); //works correctly now
var result2 = buildName("Bob", "Adams", "Sr."); //error, too many parameters
var result3 = buildName("Bob", "Adams"); //ah, just right
TypeScript
function buildName(firstName: string, lastName = "Smith") {
return firstName + " " + lastName;
}
var result1 = buildName("Bob"); //works correctly now, also
var result2 = buildName("Bob", "Adams", "Sr."); //error, too many parameters
var result3 = buildName("Bob", "Adams"); //ah, just right
function buildName(firstName: string, lastName = undefined) {
return firstName + " " + lastName;
}
enum Status { Ready, Waiting };
enum Color { Red, Blue, Green };
enum Polygon { Triangle=3, Square=4, Octagon=8 }
var status = Status.Ready;
status = Color.Green; //error
var color = Color.Blue; // 1
var colorName = Color[1]; // 'Blue'
var edges = Polygon.Octagon // 8
TypeScript
interface ILabelledValue {
label: string;
}
function printLabel(labelledObj: ILabelledValue) {
console.log(labelledObj.label)
}
var myObj = { size: 10, label: "Size 10 object" };
printLabel(myObj);
interface ILabelledValue {
label: string;
size?: number;
}
function printLabel(labelledObj: ILabelledValue) {
console.log(labelledObj.label)
}
var myObj = { count: 10, label: "Size 10 object" };
printLabel(myObj); // ok
var myObj = { size: 10, lbl: "Size 10 object" };
printLabel(myObj); // error - myObj does not satisfy LabelledValue
interface IRectangle {
x: number;
y: number;
}
interface ICuboid extends IRectangle {
z: number;
}
interface IColor {
r: number;
g: number;
b: number;
}
interface IColoredCuboid extends ICuboid, IColor{
alpha: number;
}
interface ISearchFunc {
(source: string, subString: string): boolean;
}
var mySearch: ISearchFunc;
mySearch = function(src: string, sub: string) {
var result = src.search(sub);
if (result == -1) {
return false;
}
else {
return true;
}
}
interface IStringArray {
[index: number]: string;
}
var myArray: IStringArray;
myArray = ["John", "Doe"];
interface IClock {
currentTime: Date;
setTime(d: Date);
}
class MyClock implements IClock {
currentTime: Date;
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m:number) { }
}
property
method
shared by every Object of that Class
each Object of that Class has its own copy
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
var greeter = new Greeter("world");
class Animal {
name:string;
constructor(theName: string) { this.name = theName; }
move(meters: number = 0) {
alert(this.name + " moved " + meters + "m.");
}
}
class Horse extends Animal {
constructor(name: string) { super(name); }
move(meters = 45) {
alert("Galloping...");
super.move(meters);
}
}
var tom = new Horse("Tommy the Palomino");
tom.move(34);
class Animal {
private name:string;
constructor(theName: string) { this.name = theName; }
}
class Cow extends Animal {
constructor() { super("Cow"); }
}
var horse = new Animal("horse");
var cow = new Cow();
horse.name // error
cow.name // error
class Grid {
static origin = {x: 0, y: 0};
calculateDistanceFromOrigin(point: {x: number; y: number;}) {
var xDist = (point.x - Grid.origin.x);
var yDist = (point.y - Grid.origin.y);
return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
}
constructor (public scale: number) { }
}
var grid1 = new Grid(1.0); // 1x scale
var grid2 = new Grid(5.0); // 5x scale
alert(grid1.calculateDistanceFromOrigin({x: 10, y: 10}));
alert(grid2.calculateDistanceFromOrigin({x: 10, y: 10}));
function echo(arg: any): any {
return arg;
}
function echo<T>(arg: T): T {
return arg;
}
function echo<T>(arg: T): T {
console.log(arg.length()); // error - arg might not have .length member
}
interface IHasLength {
length: number;
}
function echo<T extends IHasLength>(arg: T): T {
console.log(arg.length()); // now we know arg has a length property
}
interface IHasLength {
length: number;
}
function echo<T extends IHasLength>(arg: T): T {
console.log(arg.length()); // now we know arg has a length property
}
echo(3); // Error - number doesn't have .length property
echo({length: 5, value: 3}); // OK
class GenericClass<T>{
zeroValue: T;
add: (x:T, y:T) => T;
}
var myGenericNumberClass = new GenericClass<number>();
myGenericNumberClass.zeroValue = 0;
myGenericNumberClass.add = function(x, y) { return x + y };
var myGenericStringClass = new GenericClass<string>();
myGenericStringClass.zeroValue = "";
myGenericStringClass.add = function(x, y) { return x + y };
interface Named {
name: string;
}
class Person {
name: string;
}
var p: Named;
// OK, because of structural typing
p = new Person();
class Animal {
feet: number;
constructor(name: string, numFeet: number) { }
}
class Size {
feet: number;
constructor(numFeet: number) { }
}
var a: Animal;
var s: Size;
a = s; //OK
s = a; //OK
class Mammal {
private name: string;
constructor(_name: string) {
this.name = _name;
}
}
class Reptile {
private name: string;
constructor(_name: string) {
this.name = _name;
}
}
var cat = new Mammal('Cat');
var lizard = new Reptile('Lizard');
cat = lizard; // error: Animal and Reptile are not compatible
class Mammal {
private name: string;
constructor(_name: string) {
this.name = _name;
}
}
class Dog extends Mammal {
constructor() {
super("Dog");
}
}
var cat = new Mammal('Cat');
var dog = new Dog();
cat = dog; // OK
var x = (a: number) => 0;
var y = (b: number, s: string) => 0;
var z = (s: string) => 0;
y = x; // OK - discarding s: string
x = y; // Error
y = z; // Error
x = z; // Error
z = x; // Error
interface Empty<T> {
}
var x: Empty<number>;
var y: Empty<string>;
x = y; // okay, y matches structure of x
interface NotEmpty<T> {
data: T;
}
var x: NotEmpty<number>;
var y: NotEmpty<string>;
x = y; // error, x and y are not compatible
class Join() {
function concat (...words) {
return words.join(' ')
}
}
TypeScript
class Split {
function split (word) {
return word.split(' ');
}
}
TypeScript
class StringOperations implements Join, Split {
prefix(word) {
return "START" + word;
}
// Join
join: (string[]) => string;
// Split
split: (string) => string;
}
TypeScript
TypeScript
class StringOperations implements Join, Split {
prefix(word) {
return "START" + word;
}
}
class StringOperations implements Join, Split {
prefix(word) {
return "START" + word;
}
// Join
join: (string[]) => string;
// Split
split: (string) => string;
}
applyMixins(StringOperations, [Join, Split]);
//
// Runtime library
//
function applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
derivedCtor.prototype[name] = baseCtor.prototype[name];
})
});
}
interface IShape {
positionX : number;
positionY: number;
}
TypeScript
interface IShape {
height: number;
width: number;
}
TypeScript
var shape: IShape = { positionX: 10, positionY: 5, height: 20, width: 15 }
TypeScript
interface Document {
createElement(tagName: any): Element;
}
interface Document {
createElement(tagName: string): HTMLElement;
}
interface Document {
createElement(tagName: "div"): HTMLDivElement;
createElement(tagName: "span"): HTMLSpanElement;
createElement(tagName: "canvas"): HTMLCanvasElement;
}
TypeScript
interface Document {
createElement(tagName: "div"): HTMLDivElement;
createElement(tagName: "span"): HTMLSpanElement;
createElement(tagName: "canvas"): HTMLCanvasElement;
createElement(tagName: string): HTMLElement;
createElement(tagName: any): Element;
}
TypeScript
module Shape {
export interface IDimensions { width: number, height: number }
export class Square { }
export class Rectangle { }
export class Triangle { }
}
module Shape {
var pi = 3.1415926
export function calculateArea( radius: number ) {
return radius * radius * this.pi
}
export interface IDimensions { radius: number }
export class Circle { }
}
TypeScript
TypeScript
module Shape {
export function calculateArea( radius: number ) {
return radius * radius * this.pi
}
export interface IDimensions { width: number, height: number, radius: number }
export class Square { }
export class Rectangle { }
export class Triangle { }
export class Circle { }
}
TypeScript
module Shape {
export function calculateArea( radius: number ) {
return radius * radius * this.pi
}
export interface IDimensions { width: number, height: number, radius: number }
export class Square { }
export class Rectangle { }
export class Triangle { }
export class Circle { }
}
TypeScript
var Geometry = {
point: (function() {
function point(x, y) {
this.x = x;
this.y = y;
}
return point;
}){},
line: (function() {
function line(p1, p2) {
this.point1 = {x: p1.x, y = p1.y};
this.point2 = {x: p2.x, y = p2.y};
}
return line;
}){},
distance: function (line) {
var p1 = line.point1;
var p2 = line.point2;
return Math.sqrt(Math.pow(p2.x - p1.x, 2) +
Math.pow(p2.y - p1.y, 2)
};
};
Geometry.js
declare module MGeometry {
}
declare module MGeometry {
export interface Main {
}
}
var Geometry = {
point: (function() {
function point(x, y) {
this.x = x;
this.y = y;
}
return point;
}){},
line: (function() {
function line(p1, p2) {
this.point1 = {x: p1.x, y = p1.y};
this.point2 = {x: p2.x, y = p2.y};
}
return line;
}){},
distance: function (line) {
var p1 = line.point1;
var p2 = line.point2;
return Math.sqrt(Math.pow(p2.x - p1.x, 2) +
Math.pow(p2.y - p1.y, 2)
};
};
Geometry.js
declare module MGeometry {
export interface Main {
point:Point;
line:Line;
distance(line:Line):number;
}
}
export interface Point {
x:number;
y:number;
new(x:number, y:number):Point;
}
export interface Line {
point1:Point;
point2:Point;
new(p1:Point, p2:Point):Line;
}
var Geometry = {
point: (function() {
function point(x, y) {
this.x = x;
this.y = y;
}
return point;
}){},
line: (function() {
function line(p1, p2) {
this.point1 = {x: p1.x, y = p1.y};
this.point2 = {x: p2.x, y = p2.y};
}
return line;
}){},
distance: function (line) {
var p1 = line.point1;
var p2 = line.point2;
return Math.sqrt(Math.pow(p2.x - p1.x, 2) +
Math.pow(p2.y - p1.y, 2)
};
};
Geometry.js
declare module MGeometry {
export interface Main {
point:Point;
line:Line;
distance(line:Line):number;
}
export interface Point {
x:number;
y:number;
new(x:number, y:number):Point;
}
export interface Line {
point1:Point;
point2:Point;
new(p1:Point, p2:Point):Line;
}
declare var Geometry:MGeometry.Main;
}
David Kane
<html>
<head>
......
</head>
<body>
<app-header>
<li link="/home" class="active">Home</li>
<li link="/about">About</li>
<li link="/contact">Contact</li>
</app-header>
<app-filterlist>
<p>Item 1</p>
<p>Item 2</p>
<p>Item 3</p>
<p>Item 4</p>
<p>Item 5</p>
</app-filterlist>
<app-fatfooter>
<section>
<li link="/linkedin" class="active">LinkedIn</li>
<li link="/google">Google</li>
<li link="/facebook">Facebook</li>
</section>
<section>
<li link="/blog" class="active">Blog</li>
<li link="/youtube">Youtube</li>
</section>
</app-fatfooter>
</body>
</html>
for each page!
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex6-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Brand</a>
</div>
<div class="collapse navbar-collapse navbar-ex6-collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</div>
</nav>
<template id="myTemplate">
<img src="image.png">
<audio controls>
<source src="audio.ogg" type="audio/ogg">
<source src="audio.ogg" type="audio/mpeg">
Your browser does not support the audio tag.
</audio>
</template>
HTML
<!-- HTML holder -->
<div id="myMessage">
<h1>
This is a message
</h1>
</div>
<!-- Template -->
<template id="message">
<h1>
This is a new message
</h1>
</template>
HTML
page output
<!-- HTML holder -->
<div id="myMessage">
<h1>
This is a message
</h1>
</div>
<!-- Template -->
<template id="message">
<h1>
This is a new message
</h1>
</template>
HTML
var host = document.querySelector('#myMessage');
var root = host.attachShadow(open);
var template = document.querySelector('#message');
root.appendChild(template.content);
JavaScript
Resultant DOM:
page output
<!-- HTML holder -->
<div id="myMessage">
<h1 slot="heading">
This is a message
</h1>
<div slot="subheading">
This is another message
</div>
</div>
<!-- Template -->
<template id="message">
<div style="color:red;">
<slot name=".heading"></content>
</div>
<h2>
<slot name=".subheading"></content>
</h2>
</template>
HTML
var host = document.querySelector('#myMessage');
var root = host.attachShadow(open);
var template = document.querySelector('#message');
root.appendChild(template.content);
JavaScript
page output
<!-- HTML holder -->
<div id="myMessage">
<h1 slot="heading">
This is a message
</h1>
<div slot="subheading">
This is another message
</div>
</div>
<!-- Template -->
<template id="message">
<div style="color:red;">
<slot name=".heading"></slot>
</div>
<h2>
<slot name=".subheading"></slot>
</h2>
</template>
HTML
<div onclick="alert('fired by: ' + event.target)">
<audio controls src="test.wav"></audio>
</div>
HTML
<div><h3>Light DOM</h3></div>
HTML
var root = document.querySelector('div').attachShadow(open);
root.innerHTML = '<style>h3{ color: red; }</style>' +
'<h3>Shadow DOM</h3>';
JavaScript
page output
<template>
<style>{{ include: "./normalize.css" }}</style>
<style>{{ include "./layout-utils.css }}</style>
<div>
<!-- template elements -->
</div>
</template>
HTML
HTML
<style>
#host {
--button-text-color: green;
--button-font: "Times New Roman", Georgia, Serif;
}
</style>
<div></div>
<script>
var root = document.querySelector('div').attachShadow(open);
root.innerHTML = '<style>' +
'button {' +
'color: var(--button-text-color, blue);' +
'font-family: var(--button-font);' +
'{' +
'</style>' +
'<content></content>';
</script>
page output
<div>
<h3>Light DOM</h3>
<section>
<div>I'm not underlined</div>
<p>I'm underlined in Shadow DOM!</p>
</section>
</div>
var div = document.querySelector('div');
var root = div.attachShadow(open);
root.innerHTML = '<style>' +
'h3 { color: red; }' +
'content[select="h3"]::slotted > h3 {' +
'color: green;' +
'}' +
'::slotted section p {' +
'text-decoration: underline;' +
'}' +
'</style>' +
'<h3>Shadow DOM</h3>' +
'<slot name="h3"></slot>' +
'<slot name="section"></slot>';
HTML
JavaScript
e.g. <my-element></my-element>
distinguishes them from native HTML elements
ensures new elements (HTML6+) will not have same name as any custom elements
Use document.registerElement() to register a new element
var message = document.registerElement('my-message', {
// Inherits from base HTMLElement
prototype: Object.create(HTMLElement.prototype)
});
JavaScript
It may inherit from existing elements, e.g.
var message = document.registerElement('custom-button', {
prototype: Object.create(HTMLButtonElement.prototype),
extends: 'button'
});
JavaScript
This will create a <custom-button></custom-button> element for use in HTML
Will have all features of a <button> tag, which can be added to
Initialize element, adding child nodes:
var message = new message();
document.body.appendChild(message);
JavaScript
Lifecycle methods:
createdCallback()
when an instance of the custom element is created
attachedCallback()
when the instance is attached to the DOM
detachedCallback()
when the instance is removed from the DOM
attributeChangedCallback()
when an attribute of the instance is added, updated or removed
<html>
<head>
<link rel="import" href="/templates/my-message.html">
</head>
<body>
<my-message></my-message>
<body>
</html>
HTML
<script async>
function handleLoad(e) {
console.log('Loaded import: ' + e.target.href');
}
function handleError(e) {
console.log('Error loading import: ' + e.target.href');
}
</script>
<link rel="import" href="/templates/my-message.html"
onload="handleLoad(event)" onerror="handleError(event)">
HTML
The Jackal of Javascript (pretty exhaustive):
WebComponents.org (various resources):