Loading
Tarun Sharma
This is a live streamed presentation. You will automatically follow the presenter and see the slide they're currently on.
`strict mode`
Object...
Function...
Array...
getters/setters
modules
classes
block scopes
TCO/PTC
Symbols
rest/spread
generators
Promises
Reflections
Typed Arrays
...
'use strict';var x = 1;
function fn(){
x = 5;
var x = 0;
x; // ?
};
fn();
if ( x ){
var y = 'Im inside the block';
}
y; // ?let y = 0;
if ( true ) {
let y = 2;
console.log( y ); // 2
} else {
let y = 9;
console.log( y ); // 9
}
console.log( y ); // 0const MY_STRING_IDENTIFICATOR = 'some string';
// ...
MY_STRING_IDENTIFICATOR = 'other'; // TypeErrorvar arr = [];
for(let i = 0; i<3; i++){
arr.push(function(){
console.log(i);
});
}
arr.forEach(function(fn){
fn();
});
// var -> 3, 3, 3
// let -> 0, 1, 2var arr = [];
for(var i = 0; i<3; i++){
arr.push(function(){
console.log(i);
});
}
arr.forEach(function(fn){
fn();
});
typeof x; // ReferenceError: x is not defined
let x = 1;let x = 1;
(function (){
console.log( x ); // ReferenceError: x is not defined
let x = 2;
}());
var message = {
title : 'Hellow ',
body : 'world!'
};
var title, body;
title = message.title;
body = message.body;
title + body; // Hellow world!
// object deconstructors
let message = {
title : 'Hellow ',
body : 'world!'
};
let { title, body } = message;
title + body; // Hellow world!
// array deconstructors
let results = [ '200', { a : 1 }];
var [ status , value ] = results;
status; // 200
value; // { "a" : 1 }
let post = {
title : 'A title',
body : {
main: 'A main',
signature: 'H.J.S.'
}
};
let {
title,
body: {
main,
signature,
// setting default here
imagined_property = '- Regards'
}
} = post;
title + main + signature + imagined_property; // A title A main H.J.S. - Regardslet object = {
source_title : 'im the title',
source_body : 'and im body'
};
let {
source_title : target_title,
source_body : target_body
} = object;
target_title; // im the title
target_body; // and im bodylet object = {
source_title : 'im the title'
};
let {
source_title : target_title,
source_body : target_body = 'default body'
} = object;
target_title; // im the title
target_body; // default bodylet xyPair = [1, 5];
let point = {};
([ point.x, point.y] = xyPair );
console.log( point );
// {x: 1, y: 5}let point = {x: 1, y: 5};
let xyPair = [];
({ x : xyPair[1], y: xyPair[0] } = point );
console.log( xyPair );
// [5, 1]var o = {
name : 'Mr Objecto',
map : function(indexes){
var self = this;
indexes.map( function( index ){
console.log(index + self.name);
} );
}
};
o.map( [ 1, 2, 3] );
// 1Mr Objecto
// 2Mr Objecto
// 3Mr Objecto// this is taken from lexical scope
var o = {
name : 'Mr Objecto',
map : function(indexes){
indexes.map( index => console.log(index + this.name) );
}
};
o.map( [ 1, 2, 3] );
// 1Mr Objecto
// 2Mr Objecto
// 3Mr Objecto// inline expression with implicit return
param => expression
( par, ams ) => expression
// a block of expressions with explicit return
param => {
expressions block;
return;
}
( par, ams ) => {
expressions block;
return;
}// The brevity
// array of pairs
var array = [
[ 'a', 1 ],
[ 'b', 2 ],
[ 'c', 3 ]
];
// can be assigned, as usual funcs
var getSecondElement = pair => pair[1];
array
.map(getSecondElement)
.filter ( (element, index) => index > 0)
.forEach( el => console.log(el) );
// 2, 3function fn( a, b, c ){
if ( c === undefined ){
c = 5;
}
console.log(a,b,c);
}
fn( 1, 2, 3 ); // 1, 2, 3
fn( 1, 2 ); // 1, 2, 5function fn( a, b, c = 5 ){
console.log(a,b,c);
}
fn( 1, 2, 3 ); // 1, 2, 3
fn( 1, 2 ); // 1, 2, 5function fn( a, b, c = 1 + a ){
console.log(a,b,c);
}
fn( 1, 2 ); // 1, 2, 2// Runtime execution
let Z = 0.3;
function fn( a, b, c = Z + a ){
console.log(a,b,c);
}
fn( 1, 2 ); // 1, 2, 1.3
Z = 0.5;
fn( 1, 2 ); // 1, 2, 1.5// default value can contain any expression
let Z = 0.3;
function fn( b = ()=>{Z + 1}() ){
console.log( b );
}
fn(1); // 1
fn( ); // 1.3
Z = 0.5;
fn( ); // 1.5var x = 2, y = 3,
o = {
x: x,
y: y
};var x = 2, y = 3,
o = {
x,
y
};var o = {
x: function() {
// ..
},
y: function() {
// ..
}
}var o = {
x() {
// ..
},
y() {
// ..
}
}const PREFIX = '$';
let object = {
[ PREFIX + 'p' ] : 1,
get [ '_' + 'p' ] : 2,
[ PREFIX + 'm' ] (){
return 3;
}
};
object.$p === 1;
object._p === 2;
object.$m() === 3;
// Privates
let object = {
[ Symbol('one')] : 1,
two : 2
}
// symbols are not supposed to be accessed in the old way
Object.keys(object); // [ "two" ]
// though
Object.getOwnPropertySymbols(object); // [ Symbol(one) ]// Privates
let object = (function(){
let symbol = Symbol('one');
return {
[ symbol ] : 1,
method : function(){
return this[ symbol ];
}
};
}());
object.method(); // 1var a = {};
var prop1 = Symbol('prop');
var prop2 = Symbol('prop');
a[prop1] = 'hidden value';
a[prop2] = 'hidden value 2';
console.log(prop1); // hidden value
console.log(prop2); // hidden value 2
let hiddenShouldTrackFlagSymbol = Symbol('hidden');
function somePublicFunction( object ){
// do nothing if value in hidden property is true
if( object[ hiddenShouldTrackFlagSymbol ] )
return;
processTheObject( object );
object[ hiddenShouldTrackFlagSymbol ] = true;
}// Symbol.toPrimitive
var arr = [1,2,3,4,5];
arr + 10; // 1,2,3,4,510
arr[Symbol.toPrimitive] = function(hint) {
if (hint == "default" || hint == "number") {
// sum all numbers
return this.reduce( function(acc,curr){
return acc + curr;
}, 0 );
}
};
arr + 10; // 25
// The @@toStringTag symbol on the prototype (or instance itself)
// specifies a string value to use in the [object ___] stringification.
// The @@hasInstance symbol is a method on the constructor
// function which receives the instance object value and lets you decide by returning true or false if the value should be considered an instance or not.
function Foo(greeting) {
this.greeting = greeting;
}
Foo.prototype[Symbol.toStringTag] = "Foo";
Object.defineProperty( Foo, Symbol.hasInstance, {
value: function(inst) {
return inst.greeting == "hello";
}
} );
var a = new Foo( "hello" ),
b = new Foo( "world" );
b[Symbol.toStringTag] = "cool";
a.toString(); // [object Foo]
String( b ); // [object cool]
a instanceof Foo; // true
b instanceof Foo; // falseother WKS
let arr = [3, 5, 7];
arr.foo = "hello";
for (let i in arr) {
console.log(i); // logs "0", "1", "2", "foo"
}
for (let i of arr) {
console.log(i); // logs "3", "5", "7"
}Iterator [required]
next() {method}: retrieves next IteratorResult
Iterator [optional]
return() {method}: stops iterator and returns IteratorResult
throw() {method}: signals error and returns IteratorResult
IteratorResult
value {property}: current iteration value or final return value
(optional if `undefined`)
done {property}: boolean, indicates completion statusvar a = {}
// NOTE: Symbol.iterator
a[Symbol.iterator] = function (){
let value = 0,
done = false;
return {
next: function(){
value++;
done = value > 5;
return { done, value };
}
}
}
for( let i of a ){
console.log(i);
}
// 1, 2, 3, 4, 5function setPoints(x, y){
var points = Array.prototype.slice.call(arguments, 2);
console.log(x, y, points);
}
setPoints(0, 1, 'x0', 'x1', 'x2', 'x3');
// 0 1 ["x0", "x1", "x2", "x3"]function setPoints(x, y, ...points){
console.log(x, y, points);
}
setPoints(0, 1, 'x0', 'x1', 'x2', 'x3');
// 0 1 ["x0", "x1", "x2", "x3"]function point(x, y){
console.log('x is: ', x)
console.log('y is: ', y);
}
point(...[1, 2]);
// x is: 1
// y is: 2
var letters = ['a', 'b', 'c'];
var arr = [1, ...letters, 2, 3];
// [ 1, 'a', 'b', 'c', 2, 3 ]class A {
constructor(name){
console.log('a ' + name + ' being created');
}
}
var a = new A('Johnny'); // a Johnny being createdclass A {
constructor(){
}
method (){
}
}class A {
constructor(){ }
method (){ }
}
class B extends A {
constructor(){
super(); // call super constructor
// following initialization logic
}
}
var b = new B();class A {
constructor(){ }
method (){ }
}
class B extends A {
constructor(){
super();
}
method(){
super.method(); // can access `super` with it's methods
}
}class A {
constructor(){
if ( new.target === A )
console.log('A creating');
else
console.log('Other');
}
method (){ }
}
class B extends A {
constructor(){
super();
}
method(){
super.method();
}
}
new B(); // -> Other
new A(); // -> A creatingclass A {
static method (){ }
}
A.method();console.log(`Im multi
line string`);
// Im multi
// line stringlet amout = 1;
console.log(`This item will cost ${ amout } USD`);
// This item will cost 1 USDfunction tag( strings, ...values ){ /*...*/ }
tag `Some ${ value } text`;function bolden( strings, ...values ){
let result = strings[ 0 ];
for(let i = 1; i < strings.length; i++ ){
result += values[i-1].toString().bold() + strings[i];
}
return result;
}
console.log(bolden `You have earned ${ 4 } points out of ${ 5 } possible`);
// You have earned <b>4</b> points out of <b>5</b> possibletypeof `some text` === 'string';
(`s${ 'o' }me`).toUpperCase(); // SOME
function factorial(n) {
if (n == 0) {
return 1;
} else {
return n * factorial(n-1);
}
}function factorial(n) {
function recur(n, acc) {
if (n == 0) {
return acc;
} else {
return recur(n-1, n*acc);
}
}
return recur(n, 1);
}https://taylodl.wordpress.com/2013/06/07/functional-javascript-tail-call-optimization-and-trampolines/
export function foo() {
// ..
}
export var awesome = 42;
var bar = [1,2,3];
export { bar };function foo() {
// ..
}
var awesome = 42;
var bar = [1,2,3];
export { foo, awesome, bar };function foo() { .. }
export { foo as bar };var awesome = 42;
export { awesome };
setTimeout( ()=> { awesome = 100; }, 1000 ); // imported value will be updatedfunction foo(..) {
// ..
}
export default foo;import { foo, bar, baz } from "foo";import { foo } from "foo";
foo();import { foo as theFooFunc } from "foo";
theFooFunc();import foo from "foo";
// or:
import { default as foo } from "foo";var s = new Set();
var x = { id: 1 },
y = { id: 2 };
s.add( x ).add( y ).add( x );
s.size; // 2
s.delete( y );
s.size; // 1
s.clear();
s.size;var m = new Map();
var x = { id: 1 },
y = { id: 2 };
m.set( x, "foo" );
m.set( y, "bar" );
m.get( x ); // "foo"
m.get( y ); // "bar"
m.forEach(x=> console.log(x)); // foo, barvar SIMPLE_OBJECT = {},
OTHER_OBJECT;
var set = new WeakSet([{},{}, OTHER_OBJECT ]);
set.add( SIMPLE_OBJECT );
set.delete(OTHER_OBJECT);
set.has(SIMPLE_OBJECT); // -> true// how many times an object in a game has been interacting with the User
var weakMap = new WeakMap();
function updateInteractionCount( obj ){
var interactionTime = weakMap.get(obj) || 0;
interactionTime++;
weakMap.set(obj, interactionTime);
}
function getInteractionCount( obj ){
return weakMap.get( obj );
}
new Promise( function ( resolve, reject ) { /*...*/ } );// wait for all
Promise.all(iterable)
// wait for first
Promise.race(iterable)
// create immediately rejected future
Promise.reject(reason)
// create immediately resolved future
Promise.resolve(value)var promise = new Promise(( resolve, reject ) => setTimeout( resolve, 100 ));
// `new` is a must
console.log(0);
promise
.then( ()=> console.log(1) )
.then( ()=> { throw 2; } )
.catch( (exc)=> console.log(exc))
.then( ()=> console.log(3) );
console.log(4);
// 0
// 4
// 1
// 2
// 3
var createPromise = ( time ) => {
// return a promise, that will be resolved in a time
return new Promise( resolve => {
setTimeout( ()=>{
console.log('logging after: ', time);
resolve( time );
}, time );
} )
};
var p1 = createPromise(100);
var p2 = createPromise(500);
var p3 = createPromise(250);
console.log('Start');
Promise
.all([ p1, p2, p3 ])
.then( ()=>{ console.log('Done'); } );
console.log('Finish');// Start
// Finish
// logging after: 100
// logging after: 250
// logging after: 500
// Donefunction *generator(){
yield 1;
yield 2;
yield 3;
}
for(let i of generator()){
console.log(i);
}
// 1
// 2
// 3function *otherGenerator(){
yield 'A';
yield 'B';
yield 'C';
}
function *generator(){
yield 1;
yield* otherGenerator();
yield 2;
yield 3;
}
for(let i of generator()){
console.log(i);
}// 1
// A
// B
// C
// 2
// 3function *generator( x ){
let a = yield( x + 1 ); // after continuing, a = 0.5
let b = yield( a * 2 ); // after continuing, b = 1
return a + b;
}
let iterator = generator(3); // instantiate
let xPlus1 = iterator.next(); // {value: 4, done: false}
let aMultipl2 = iterator.next(0.5); // {value: 1, done: false}
let result = iterator.next(1); // {value: 1.5, done: true}
function *fibonacci(){
let pprev = 0,
prev = 1,
result = 0;
yield prev;
while(true){
result = pprev + prev;
pprev = prev;
prev = result;
yield result;
}
}
let iterator = fibonacci();
for( let i = 0; i < 4; i++ ){
console.log(iterator.next().value); // 1 1 2 3
}function run(fn){
let it = fn();
(function iterry(value){
let yie = it.next(value);
if (yie.done) return yie.value;
if (yie.value.then){
yie.value.then(iterry);
} else {
iterry(yie.value)
}
}());
}// async method, returning promises,
// autoresolving in some time in future
function requesto(msg){
return new Promise(resolve => {
setTimeout(()=>{
resolve(`< ${msg} />`);
}, 1000);
});
}
console.log('Starting');
run(function*(){
let items = yield requesto('items');
let subitems = yield requesto(items);
console.log( 'items:', items)
console.log( 'subitems:', subitems);
});
console.log('Ending');
// Starting
// Ending
// items: < items />
// subitems: < < items /> />run(function*(){
try{
let items = yield requesto('items');
let subitems = yield requesto(items);
console.log( 'items:', items)
console.log( 'subitems:', subitems);
} catch( exc ){
console.error( 'PANIC' );
}
});
Normal exception flow
welcome to the woorrlld of tomorrowww
ES7
Decorators make it possible to annotate and modify classes and properties at design time.
class Person {
@nonenumerable
get kidCount() { return this.children.length; }
}
function nonenumerable(target, name, descriptor) {
descriptor.enumerable = false;
return descriptor;
}change enumerability of a property
class Person {
@memoize
get name() { return `${this.first} ${this.last}` }
set name(val) {
let [first, last] = val.split(' ');
this.first = first;
this.last = last;
}
}
let memoized = new WeakMap();
function memoize(target, name, descriptor) {
let getter = descriptor.get, setter = descriptor.set;
descriptor.get = function() {
let table = memoizationFor(this);
if (name in table) { return table[name]; }
return table[name] = getter.call(this);
}
descriptor.set = function(val) {
let table = memoizationFor(this);
setter.call(this, val);
table[name] = val;
}
}
function memoizationFor(obj) {
let table = memoized.get(obj);
if (!table) { table = Object.create(null); memoized.set(obj, table); }
return table;
}Watches for changes in an object and notifies of such in async way
// Let's say we have a model with data
var model = {};
// Which we then observe
Object.observe(model, function(changes){
// This asynchronous callback runs
changes.forEach(function(change) {
// Letting us know what changed
console.log(change.type, change.name, change.oldValue);
});
});
model.itemNumber = 1;
// add itemNumber undefined
model.itemNumber = 2;
// update itemNumber 1One of the uses of SIMD is to accelerate processing of large arrays of data. If you have an array of N elements, and you want to do roughly the same thing to every element in the array, you can divide N by whatever SIMD size the platform makes available and run that many instances of your SIMD subroutine...
Another use of SIMD is to accelerate processing of clusters of data. RGB or RGBA pixels, XYZW coordinates, or 4×4 matrices are all examples of such clusters...
// https://github.com/yortus/asyncawait
var foo = async (function() {
var resultA = await (firstAsyncCall());
var resultB = await (secondAsyncCallUsing(resultA));
var resultC = await (thirdAsyncCallUsing(resultB));
return doSomethingWith(resultC);
});function sleep(msg) {
return new Promise(function($return, $error) {
setTimeout(function() {
$return(msg + " world");
}, 100);
});
}
console.log("Starting");
var c = await sleep("hellow");
console.log(c);
// Starting
// hellow worldtry async/await live @ http://nodent.mailed.me.uk/