David Kane
New features in ES6
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
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
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
// 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
class ClientService {
clients = [];
addClient(client) {
this.clients.add(client);
}
}
export default ClientService;
ES6
// 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 ClientService = require('./ClientService');
CommonJS
import ClientService from ('./ClientService');
ES6
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() {
incomes.incomeSupport = this.valIncomeSupport;
incomes.jobseekers = this.valJobseekers;
incomes.incapacity = this.valIncapacity;
this.valTotalBenefitIncome = incomes.TotalBenefitIncome;
}
// IncomesController.js
var incomeSupport;
var jobSeekers;
var incapacity;
var totalBenefitIncome = function() {
this.valIncomeSupport +
this.valJobSeekers +
this.valIncapacity;
}
// ChangeNumber.js
var changingNumber = 1;
var changeNumber = function() {
this.changingNumber += 1;
}
export changingNumber;
export changeNumber;
import {changingNumber, changeNumber}
from './ChangeNumber';
console.log(changingNumber); // changingNumber = 1
changeNumber;
console.log(changingNumber); // changingNumber = 2
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]();
ES6
> 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 foo = { [Symbol.iterator]: iterable } or foo[Symbol.iterator] = iterable
[Symbol.iterator]: () => ({
items: ['f', 'o', 'o'],
next: function next() {
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
const stuff = { things: ['chair', 'desk', 'computer'] };
e.g.
const stuff = { things: ['chair', 'desk', 'computer'] };
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.
var arrow = function() {}
var arrow = () => {}
becomes
function() {}
() => {}
becomes
function(a) { return a * a }
a => a * a
becomes
function(a, b) { return a + b }
(a, b) => a + b
becomes
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' });
ES6
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("benefits-panel"), { display: true });
add(document.getElementById("otherincome-panel"), { display: true });
ES6
add(document.getElementById("wages-panel"), { display: true });
ES6
var map = new Map();
map.set(new Date(), function today() {});
map.set(() => 'key', { foo: 'bar' });
map.set(Symbol('items'), [1, 2]);
ES6
for (let key in object) {
if (object.hasOwnProperty(key)) {
console.log(key, object[key]);
}
}
using objects
for (let key in object) {
if (object.hasOwnProperty(key) &&
typeof object[key] !== "function") {
console.log(key, object[key]);
}
}
using objects
for (let key of map.keys()) {
console.log(key);
}
for (let value of map.values()) {
console.log(value);
}
for (let entry of map) {
console.log(entry[0], entry[1]);
}
using maps
using maps
using maps
map.get("key");
get value of 'key'
map.set("key", "value");
insert new item (will overwrite a duplicate key)
map.has("key");
checks if key exists (true/false)
map.delete("key");
deletes item from map
map.size();
gets number of items in map
map.clear();
removes all items from map (without losing reference to it)
var items = [
[new Date(), function today() {})],
[() => 'key', { foo: 'bar' })],
[(Symbol('items'), [1, 2])
]
var map = new Map();
map = items;
ES6
const privateData = new Map();
class myClass {
constructor (name, age) {
privateData(this, { name: name, age: age });
}
getname () {
return privateData.get(this).name;
}
getAge() {
return privateData.get(this).age;
}
}
export default MyClass;
ES6
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;
}
}
export default MyClass;
ES6
let answersMap = new WeakMap();
let childBenefit = document.getElementById('child-benefit');
myElement.addEventListener('change', function() {
var answerFrequency = getFrequency();
answersMap.set(childBenefit, {frequency: answerFrequency}
}, false);
ES6
let childNumber = document.getElementById('child-number')
if(childNumber.number === 0) {
childBenefit.parentNode.removeChild(childBenefit)
}
ES6
console.log(answerMap.get(childBenefit) // undefined
ES6
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
@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 foo = { bar }
console.log(foo.bar) // 'bar'
ES6
var foo = 'bar'
var baz = { [foo]: 'qux' }
console.log(baz)
// { bar: 'qux' }
ES6
var foo = { [bar + baz]: 'qux' }
console.log(foo)
// { barbaz: 'qux' }
ES6
function getAnswerModel (dataItem, amt, frequency) {
return {
['ans_' + dataItem] : {
amount: amt;
frequency: freq
}
}
}
ES6
var foo = {
bar(baz) { }
}
ES6
var foo = {
bar: function(baz) { }
}
ES5
var = clientDetails {
name: 'Joe Bloggs',
get name(value) {
return this.name
},
set name(value) {
if (!value) {
throw new Error('Name invalid')
}
this.name = value
}
}
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 swapIf () {
var left = 10;
var right = 20;
var aux;
if(right > left) {
aux = right;
right = left;
left = aux;
}
}
ES5
function swapIf () {
var left = 10
var right = 20
if(right > left) {
[left, right] = [right, left]
}
}
ES6
function displayNameAge ( {name, age} ) {
console.log(`${name} is ${age} years old`)
}
displayNameAge( { age: 27, name: 'John'} ) // 'John is 27 years old'
ES6
function getCoordinates() {
return {
x: 5,
y: 22
}
}
var {x, y} = getCoords()
console.log(x) // 5
console.log(y) // 22
ES6
function getCoordinates() {
return {
x: 5,
y: 22
}
}
var object = getCoordinates();
var x = object.x;
var y = object.y;
console.log(x) // 5
console.log(y) // 22
ES5
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 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
var img = document.querySelector('.img');
img.addEventListener('load', function() {
// Image loaded
});
imag.addEventListener('error', function() {
// Error
}
ES5
var img = document.querySelector('.img');
if(img.complete) {
loaded();
}
else (
img.addEventListener('load', function() {
loaded();
});
img.addEventListener('error', function() {
// Error
}
function loaded() {
// Loaded
}
ES5
img.callThisIfLoadedOrWhenLoaded(function() {
// loaded
}).orIfFailedCallThis(function() {
// failed
});
whenAllTheseHaveLoaded([img1, img2].callThis(function() {
// loaded
}).orIfSomeFailedCallThis(function() {
// failed
});
img.ready().then(function() {
// loaded
}), function() {
// failed
});
Promise.all([img1.ready(), img2.ready()]).then(function() {
// loaded
}), function() {
// failed
});
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
ES6 Overview in 350 Bullet Points, ponyfoo.com:
2ality, various tutorials and free ES6 ebook:
HTML5 rocks (various tutorials, good explanation of Promises):
JavaScript playground (various tutorials):
Most of the code examples in this presentation are adapted from ones from the following sources:
David Kane
var n = 1
console.log(typeof(n)) // number
var s = "Hello World"
console.log(typeof(s)) // string
function f() {
return "hello"
}
console.log(typeof(f.call())) // string
TypeScript
var notSure: any = 4;
notSure = "maybe a string instead";
notSure = false;
var list:any[] = [1, true, "free"];
TypeScript
function add(num1, num2): number {
return num1 + num2;
}
function concat(str1, str2): string {
return str1 + str2;
}
TypeScript
function warnUser(): void {
alert("This function doesn't return a type");
}
TypeScript
function add(num1: number, num2: number) {
return num1 + num2;
}
function concat(str1: string, str2: string) {
return str1 + str2;
}
TypeScript
function getRange(max, min, exclusive?) {
// ...
}
TypeScript
function getRange(max, min, exclusive = undefined) {
// ...
}
TypeScript
enum Color {Red, Green, Blue}
var colorName: string = Color[2]
alert(colorName) // 'Green'
TypeScript
enum Color {Red = 3, Green = 1, Blue = 2}
var colorName: string = Color[1]
alert(colorName) // 'Green'
TypeScript
interface ILabelledValue {
label: string;
}
function printLabel(labelledObj: ILabelledValue) {
console.log(labelledObj.label)
}
var myObj = { size: 10, label: "Size 10 object" };
printLabel(myObj);
TypeScript
interface ILabelledValue {
label: string;
size?: number;
}
TypeScript
function printLabel(labelledObj: ILabelledValue) {
console.log(labelledObj.label)
}
var myObj = { sise: 10, label: "Size 10 object" };
printLabel(myObj); // error - myObj does not satisfy LabelledValue
TypeScript
interface IRectangle {
x: number;
y: number;
}
interface ICuboid extends IRectangle {
z: number;
}
TypeScript
TypeScript
interface IColor {
r: number;
g: number;
b: number;
}
interface IColoredCuboid extends ICuboid, IColor {
alpha: number;
}
TypeScript
TypeScript
interface ISearchFunc {
(source: string, subString: string): boolean;
}
TypeScript
var mySearch: ISearchFunc;
mySearch = function(src: string, sub: string) {
var result = src.search(sub);
if (result == -1) {
return false;
}
else {
return true;
}
}
TypeScript
interface IStringArray {
[index: number]: string;
}
var myArray: IStringArray;
myArray = ["John", "Doe"];
TypeScript
interface IClock {
currentTime: Date;
setTime(d: Date);
}
class MyClock implements IClock {
currentTime: Date;
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m:number) { }
}
TypeScript
property
method
shared by every Object of that Class
each Object of that Class has its own copy
class Mammal {
private name: string;
constructor(_name: string) { this.name = _name; }
}
TypeScript
class Reptile {
private name: string;
constructor(_name: string) { this.name = _name; }
}
TypeScript
var cat = new Animal('Cat');
var lizard = new Animal('Lizard');
cat = lizard; // error: Animal and Reptile are not compatible
class Mammal {
private name: string;
constructor(_name: string) { this.name = _name; }
}
TypeScript
class Dog extends Animal {
constructor() { super("Dog"); }
}
TypeScript
var cat = new Animal('Cat');
var dog = new Dog();
cat = dog; // OK
function echo(arg: any): any {
return arg;
}
TypeScript
function echo<T>(arg: T): T {
return arg;
}
TypeScript
function echo<T>(arg: T): T {
console.log(arg.length()); // error - arg might not have .length member
}
TypeScript
interface IHasLength {
length: number;
}
function echo<T extends IHasLength>(arg: T): T {
console.log(arg.length()); // now we know arg has a length property
}
TypeScript
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
TypeScript
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 };
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;
}
}
TypeScript
class StringOperations implements Join, Split {
prefix(word) {
return "START" + word;
}
// Join
join: (string[]) => string;
// Split
split: (string) => string;
}
applyMixins(StringOperations, [Join, Split]);
function applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
derivedCtor.prototype[name] = baseCtor.prototype[name];
})
});
}
TypeScript
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;
}
TypeScript handbook (pretty much everything you need to know):
Language specification (uses a lot of the same examples):
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):