The road to
ES Next.
By Mahdi Pedramrazi
April 2017
Mahdi Pedram
eBay Buyer Experience & Verticals
JavaScript Developer
Agenda
- History of JavaScript
- ES2015 Syntax & Examples
- Resources
- Q&A
History of JavaScript
Birth of Mocha by Brendan Eich
in 10 days
May 1995
![](https://s3.amazonaws.com/media-p.slid.es/uploads/30290/images/3748235/eich.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/30290/images/3748785/1_copy_copy.png)
Renamed to LiveScript
Sep 1995
Netscape Navigator 2.0 beta release
![](https://s3.amazonaws.com/media-p.slid.es/uploads/30290/images/3748790/2_copy_copy.png)
Renamed to JavaScript
Dec 1995
Netscape Navigator 2.0 beta 3 release
![](https://s3.amazonaws.com/media-p.slid.es/uploads/30290/images/3748793/3_copy_copy.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/30290/images/3748796/4_copy_copy.png)
ECMAScript is standard specification to standardize JavaScript
ECMAScript published in the first edition of the ECMA-262 standard in June 1997.
![](https://s3.amazonaws.com/media-p.slid.es/uploads/30290/images/3748798/5_copy_copy.png)
ECMAScript
Second Edition
June 1998
Editorial changes
![](https://s3.amazonaws.com/media-p.slid.es/uploads/30290/images/3748801/6_copy_copy.png)
ECMAScript
Third Edition
December 1999
regular expressions
try/catch exception handling
![](https://s3.amazonaws.com/media-p.slid.es/uploads/30290/images/3748803/7_copy_copy.png)
ECMAScript
Forth Edition
Never Happened
Some features dropped.
Some feature proposed for Harmony release.
![](https://s3.amazonaws.com/media-p.slid.es/uploads/30290/images/3748808/8_copy_copy.png)
ECMAScript
Fifth Edition
Dec 2009
strict mode
JSON
reflection on object properties
![](https://s3.amazonaws.com/media-p.slid.es/uploads/30290/images/3748811/9_copy_copy.png)
ECMAScript
5.1 Edition
June 2011
revision of 5.0 that corrects some errors in the document
![](https://s3.amazonaws.com/media-p.slid.es/uploads/30290/images/3748812/10_copy_copy.png)
ECMAScript
6th Edition - ES2015
June 2015
new syntax
classes & modules
iterators & for-of loop
collections
promises
reflection & proxies
![](https://s3.amazonaws.com/media-p.slid.es/uploads/30290/images/3748816/11_copy_copy.png)
ECMAScript
ES 2016
June 2016
exponentiation operator (**) Array.prototype.includes.
![](https://s3.amazonaws.com/media-p.slid.es/uploads/30290/images/3748817/12_copy_copy.png)
ECMAScript
ES 2017
Stage 4
Async Functions
Shared memory and atomics
ES2015 Syntax
ES2015 Syntax
- Block Scope Declaration
- Spread/Rest Operator
- Default Parameter Values
- Destructuring
- Object Literal Extensions
- Arrow Functions
- for..of loop
- Symbols & Iterators
Block Scope Declaration
<ES2015 block scope variables wasn't supprted
Variables are function scoped
function person() {
var name = "john";
var age = 30;
console.log(str); // prints: undefined
if (age > 25) {
var str = "It's time to work harder";
console.log(str); // prints: "It's time to work harder"
}
console.log(str); // prints: "It's time to work harder"
}
Variable declaration gets Hoisted to the top.
function person() {
var name = "john";
var age = 30;
var str;
console.log(str); // prints: undefined
if (age > 25) {
str = "It's time to work harder";
console.log(str); // prints: "It's time to work harder"
}
console.log(str); // prints: "It's time to work harder"
}
hoisted to the top
Text
Hoisted variables are initialized with undefined
ES2015
Block Scope variables
let & const
Block Scoping with let
var name = "John";
{
let name = "Paul";
console.log(name); // prints: Paul
}
console.log(name); // prints: John
not initialized until they appear in the block
Temporal Dead Zone (TDZ)
{
console.log(a); // undefined
console.log(b); // Uncaught ReferenceError: b is not defined.
// `b` is declared but it's in TDZ.
if (typeof b === undefined) { // ReferenceError
//..
}
var a;
let b;
}
Accessing too early let references are called TDZ
Initially, storage space (binding) is created for the let variable but the variable remains uninitialized
Use let in for loops
for (let j=0; j < 5; j++){
setTimeout(function() {
console.log(j); // 0 1 2 3 4
}, 1000)
}
j is redeclared in every iteration.
Creates a new lexical scope in each iteration
for (var i=0; i < 5; i++){
setTimeout(function() {
console.log(i); // 5 5 5 5 5
}, 1000)
}
i is defined once, hoisted to the top of the function.
when setTimeout gets executed i === 5
Const Declaration
Creates a read only variable after the initial value is set.
- All const variables should be declared and initialized.
- "const" variables can't get reassigned.
Note: not restricted on the value but on variable assignment.
{
const name = "john";
console.log(name); // john
name = "alex"; // TypeError!
const arr = [1, 2, 3];
arr.push(4);
arr; // [1,2,3,4];
arr = 5; // TypeError.
const a; // Uncaught SyntaxError: Missing initializer in const declaration
}
Block-Scoped function
functions declared inside a block are block scoped.
var a = 1;
if (a === 1) {
function foo() {
console.log("1");
}
} else {
function foo() {
console.log("2");
}
}
foo() // <ES6 environment prints 2.
// ES6 throws ReferenceError
ES2015 Syntax
- Block Scope Declaration
- Spread/Rest Operator
- Default Parameter Values
- Destructuring
- Object Literal Extensions
- Arrow Functions
- for..of loop
- Symbols & Iterators
Spread/Rest Operator
Spread Operator
use ... behind an any iterable.
spread out to individual values
function numbers( a, b, c ) {
console.log(a, b, c); // 1 2 3
}
numbers(1, 2, 3);
numbers(...[1 ,2 ,3]);
expand value or spreading out in other context
var a = [2, 3, 4];
var b = [1, ...a, 5];
console.log(b); // [1, 2, 3, 4, 5];
Rest Operator
use ... gathers set of of values to combine values
function numbers( a, b, ...z ) {
console.log(a, b, z); //1 2 [3, 4, 5]
}
numbers(1, 2, 3, 4, 5);
No more arguments Object
...args gathers all parameters.
great replacement for arguments object
function numbers(...args) {
args.shift();
console.log(...args); // 2 3 4
}
numbers(1, 2, 3, 4);
function numbers() {
var args = Array.prototype.slice.call(arguments);
args.shift();
console.log.apply(null, args); // 2 3 4
}
numbers(1, 2, 3, 4);
pre ES6
Array-Like object
rest operator
spread operator
ES2015 Syntax
- Block Scope Declaration
- Spread/Rest Operator
- Default Parameter Values
- Destructuring
- Object Literal Extensions
- Arrow Functions
- for..of loop
- Symbols & Iterators
Default Parameter Values
Pre ES6
No Default Value
function foo(x, y) {
x = x || 10;
y = y || 20;
console.log( x + y);
}
foo(0, 6); // 16
Expected 6
0 is falsy
Default Parameter Values
function foo(x = 10, y = 20) {
console.log( x + y);
}
foo(null, 6); // 6 <-- null coerces to 0
foo(0, 6); // 6
foo(5, undefined) // 25 <-- undefined interprets as missing
foo(5, null); // 5 <-- null coerces to 0
ES6 version
undefined interprets as missing
null coerces to 0
Required Parameters
function required() {
throw new Error('Missing parameter');
}
function foo(mustBeProvided = required()) {
return mustBeProvided;
}
foo(); // Uncaught Error: Missing parameter
Example:
use default values for required parameters
ES2015 Syntax
- Block Scope Declaration
- Spread/Rest Operator
- Default Parameter Values
- Destructuring
- Object Literal Extensions
- Arrow Functions
- for..of loop
- Symbols & Iterators
Destructuring
Structured Assignment
function names() {
return ["John", "Alex", "Mike"];
}
var tmp = names(),
john = tmp[0],
alex = tmp[1],
mike = tmp[2];
manually assigning indexed values from an array
function values() {
return {
a: 1,
b: 2;
}
}
var tmp = values(),
a = tmp.a,
b = tmp.b;
manually assigning property values from an object
- manual or structured assignment needs extra variables
- lots of boilerplate code
Destructuring
- no need for additional temp variables.
- much cleaner
function names() {
return ["John", "Alex", "Mike"];
}
var [ john, alex, mike ] = names();
console.log(john, alex, mike); // John Alex Mike
array destructuring
function values() {
return {
a: 1,
b: 2;
}
}
var { a, b } = values();
console.log(a, b); // 1 2
object destructuring
Assignment not declaration
function values() {
return {
a: 1,
b: 2
}
}
var a, b;
({ a, b} = values());
[ c, d ] = [3, 4];
Destructuring is a general assignment operation not a declaration
wrap object destructuring in (...).
Objects: Variable Alias
- Data gets stored in variable alias or target.
- Source and target variables are the same, no need to change
function values() {
return {
a: 1,
b: 2;
}
}
var { a: firstNumber, b } = values();
console.log(firstNumber, b); // 1 2
console.log(a); // Reference Error
variable alias
{ a, b } // source and target are the same
{ a: a, b: b } // same as above - source and target are the same
variable alias
source
Mapping & Transformation
Any valid assignment expression is allowed
for both Array destructuring and Object destructuring.
// Object mapping and transformation
var obj = { a: 1, b: 2 };
var o = {};
({ a: o.x, b: o.y } = obj);
console.log(o.x, o.y) // 1 2
// Array transformation - reordering
var a1 = [ 1, 2, 3],
a2;
[ a2[2], a2[0], a2[1] ] = a1
console.log(a2); // [2, 3, 1]
//-----Mapping Object to Array--------
var obj = { a: 1, b: 2 };
var arr = [];
({ a: arr[0], b: arr[1] } = obj);
console.log(arr[0], arr[1]) // 1 2
//-----Mapping Array to Object--------
var a1 = [ 1, 2, 3],
o = {};
[ o.a, o.b, o.c] ] = a1;
console.log(o.a, o.b, o.c); // 1 2 3
Object/Array mapping and transformations
Map an Array to an Object or visa versa
No need to assign all values
var arr = [ 1, 2, 3];
var [ ,,c ] = arr
console.log(c); // 3;
var obj = { a: 2 };
var { b } = obj;
console.log(b); // undefined
use "," to skip an index
variable that is not defined will be assigned undefined
var arr1 = [2, 3, 4];
var [ b, ...c ] = arr1;
console.log(c) // [3, 4]
use rest operator ... for gather behaviour
Default Value Assignment
var [ a = 10, b = 4, c] = [undefined, 1, 2];
console.log(a, b, c); // 10 1 2
var { x, y, z = 10, k: KK = 20 } = { x: 1, y: 2, z: 3, k: undefined };
console.log(x, y, z, KK); // 1 2 3 20
Array:
Object:
Nested Destructuring
var [a, [b, c, d], e] = [ 1, [2, 3, 4], 5];
console.log( a, b, c, d, e); // 1 2 3 4 5
var App = {
model: {
Item: function() {}
}
};
var { model: { Item } } = App;
// instead of
var Item = App.model.Item;
destructure nested arrays
destructure object namespaces
Destructure Parameters
function numbers([x, y]) {
console.log(x, y);
}
numbers( [1, 2] ); //1 2
numbers( [1] ); // 1 undefined
numbers( [] ); // undefined undefined
numbers(); // uncaught Exception - TypeError
Default values replace undefined values
array destructuring for parameters
object destructuring for parameters
function numbers({x, y}) {
console.log(x, y);
}
numbers( { x :1, y: 2 ); //1 2
numbers( { x: 1 } ); // 1 undefined
numbers( {} ); // undefined undefined
numbers(); // uncaught Exception - TypeError
uncaught exception
Destructure Defults
function numbers([x, y = 5] = []) {
console.log(x, y);
}
numbers(); // undefined 5
array destructuring for parameters
default object properties overwrites destructured values.
function numbers({x = 1, y = 1} = { x: 3}) {
console.log(x, y);
}
numbers(); // 3 1
numbers({}); // 1 1
Assign default array or object when no parameter is passed.
Assign default values for destructured variables
ES2015 Syntax
- Block Scope Declaration
- Spread/Rest Operator
- Default Parameter Values
- Destructuring
- Object Literal Extensions
- Arrow Functions
- for..of loop
- Symbols & Iterators
Object Literal Extensions
Concise Properties
Properties that are the same name as lexical identifier can get shorten
var a = 1;
var b = 2;
var o = {
a: a,
b: b
};
a: a looks redundant
var a = 1;
var b = 2;
var o = {
a,
b
};
Concise Methods
new way: function shorthand
var o = {
a: function() { ... },
b: function() { ... }
};
old way
var o = {
a() { ... },
b() { ... }
};
Computed Property Names
var str = "string";
var o = {
["some string"]: 1,
["some " + str]() { ... }
};
any valid expression can appear inside the [...]
Object Super
var animal = {
eat() {
console.log("animal:eat");
}
};
var dog = {
eat() {
super.eat();
console.log("dog:eat");
}
};
Object.setPrototypeOf( dog, animal );
dog.eat(); // animal:eat
// dog:eat
Object.getPrototypeof(dog) // animal object
super is allowed only in consise methods.
super is locked statically to the prototype of dog
Concise Methods Gotcha
Concise method imply anonymous function expression.
not a good idea for recursion or event binding
function func(obj) { ... }
func({
someMethod() {
if(...) {
return someMethod(); //uncaught exception - ReferenceError
}
}
});
something: function() {} // anonymous function expression
something: function something() {} // named function expression
Inner function used for recursion
ES2015 Syntax
- Block Scope Declaration
- Spread/Rest Operator
- Default Parameter Values
- Destructuring
- Object Literal Extensions
- Arrow Functions
- for..of loop
- Symbols & Iterators
Arrow Functions
Arrow Functions
function example(a, b) {
a *= 2;
b *= 3;
return a + b;
}
var example = (a, b) => {
a *= 2;
b *= 3;
return a + b;
}
a regular function declaration
Arrow function
Arrow functions are always anonymous function expressions.
Arrow Functions guidelines
var f1 = (a, b) => {
a++;
b++;
return a + b;
};
var f3 = (x, y) => x + y;
No parameter always needs ( )
Single Parameter: no need for ( )
var f1 = x => x * 2;
2+ Parameter: requires ( )
More than one statement requires { ... }
var f1 = () => 5;
Arrow Functions Example
var a = [1, 2, 3];
var b = a.map(function(n) {
return n * 2;
});
console.log(b) // [2, 4, 6];
old style
var a = [1, 2, 3];
var b = a.map(n => n * 2);
console.log(b) // [2, 4, 6];
new style
Arrow Functions Advantages
1. Shorter Syntax
2. this has a lexical scope.
lexically inherits "this" from the surrounding scope
3. Does not bind this, arguments, super, or new.target.
Example
var controller = {
makeRequest: function(){
var self = this;
btn.addEventListener("click", function() {
self.makeRequest(...);
}
}
};
var controller = {
makeRequest: function(){
btn.addEventListener("click", () => {
this.makeRequest(...);
}
}
};
Lexical Scope
Dynamic Scope
ES2015 Syntax
- Block Scope Declaration
- Spread/Rest Operator
- Default Parameter Values
- Destructuring
- Object Literal Extensions
- Arrow Functions
- for..of loop
- Symbols & Iterators
for..of loop
loops over the set of values produced by an iterator
for..of loop
Arrays
Strings
Generators
Collections
Built-in Iterables
for..of loop
var arr = [1, 2, 3, 4];
for (let val of arr) {
console.log(val); // 1 2 3 4
}
var arr = [1, 2, 3, 4];
var val;
for (var i = 0; i < arr.length; i++) {
val = arr[i];
console.log(val); // 1 2 3 4
}
pre ES6
ES6
under the hood
var arr = [1, 2, 3, 4];
for (let val of arr) {
console.log(val); // 1 2 3 4
}
var a = [1, 2, 3, 4];
for (
let ret,
it = a[Symbol.iterator]();
( ret = it.next()) && !ret.done; )
{
console.log(ret.value); // 1 2 3 4
}
under the hood
ES6
ES2015 Syntax
- Block Scope Declaration
- Spread/Rest Operator
- Default Parameter Values
- Destructuring
- Object Literal Extensions
- Arrow Functions
- for..of loop
- Symbols & Iterators
Symbols & Iterators
Symbols
Note:
- Don't write new Symbol it's not a constructor
- use
typeof operator to identify
var symbol = Symbol("some description");
typeof symbol // "symbol"
new Symbol() // Uncaught TypeError: Symbol is not a constructor
- New primitive type
- value is hidden an unobtainable
- string-like value that can't collide with other values
Symbols
Note:
- if it finds in the registry it will return in
- if it doesn't find it creates a new one and return it.
- make sure to namespace your symbols
var EVT_LOGIN = Symbol("event.login");
evthub.listen( EVT_lOGIN, () => { ... });
Available in the function scope
var EVT_LOGIN = Symbol.for("event.login");
evthub.listen( EVT_lOGIN, () => { ... });
Global symbol registry: Symbol.for("...");
Symbols: accessing key
var s = Symbol.for("event.login");
var desc = Symbol.keyFor(s);
console.log( desc ); // event.login
use Symbol.keyFor() to extract the key
Symbol.iterator
var arr = [1, 2, 3];
var it = arr[Symbol.iterator]();
it.next(); // { value: 1, done: false }
it.next(); // { value: 2, done: false }
it.next(); // { value: 3, done: false }
it.next(); // { value: undefined, done: true }
array example
Symbol.iterator is a built in symbol
Collections
var m = new Map();
m.set( "key 1", 1 );
m.set( "key 2", 2);
var it = m.entries();
it.next(); // { value: ["key 1", 1], done: false }
var it = m[Symbol.iterator]();
it.next(); // { value: ["key 1", 1], done: false }
Map example
.entries() returns an iterator
Custom Iterators
var Fib = {
[Symbol.iterator]() {
var n1 = 1;
var n2 = 1;
return {
//make the iterator an iterable
[Symbol.iterator]() { return this; },
next() {
var current = n1;
[n1, n2] = [n2, n1 + n2];
if(current > 10 ) {
return { done: true}
}
return { value: current, done: false};
},
// will get called on break, continue, throw, return
return(v) {
return { value: v, done: true }
}
}
}
};
for (var v of Fib) {
console.log(v);
}
var iterator = Fib[Symbol.iterator]();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
What's Next
ECMAScript 2017.
Async functions
Shared memory and atomics
References
You Don't Know JS: ES6 & Beyond
by Kyle Simpson
Understanding ECMAScript 6: The Definitive Guide for JavaScript Developers
By Nicholas c Zakas
![](https://s3.amazonaws.com/media-p.slid.es/uploads/30290/images/3749124/es6_1.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/30290/images/3749127/Screen_Shot_2017-04-27_at_9.46.12_PM.png)
Overwhelmed with tools
![](https://s3.amazonaws.com/media-p.slid.es/uploads/30290/images/3744944/FOREST.jpg)
Focus on Fundamentals
![](https://s3.amazonaws.com/media-p.slid.es/uploads/30290/images/3744951/eagle_a.jpg)
Thank You
Q&A
The road to ES Next.
By pedramphp
The road to ES Next.
History of JavaScript and ES2015 syntax
- 2,410