ECMAScript
ES2015, ES2016, ES2017
Samuel Silva
Arrow Function, Classes, Destructuring Assignment, Spread, Rest
What the heck is ECMAScript?
The ECMAScript specification is a standardized specification of a scripting language developed by Brendan Eich of Netscape.
Initially it was named Mocha, later LiveScript, and finally JavaScript
ES2015
- June 2015
- Initially known as ECMAScript 6 (ES6) and later renamed to ECMAScript 2015 (ES2015)
- Iterators and for/of loops, Python-style generators and generator expressions, arrow functions, binary data, typed arrays, collections (maps, sets and weak maps), promises, number and math enhancements, reflection, and proxies (metaprogramming for virtual objects and wrappers)
ES2016
- June 2016
- the exponentiation operator (**) and Array.prototype.includes
ES2017
- June 2017
- includes features for concurrency and atomics, syntactic integration with promises (async/await)
Arrow Function
An arrow function expression has a shorter syntax than a function expression and does not have its own this, arguments, super, or new.target. These function expressions are best suited for non-method functions, and they cannot be used as constructors.
const sum = (arg1, arg2) => {
return arg1 + arg2
}
const sum = (arg1, arg2) => arg1 + arg2
const test = arg1 => arg1
Arrow Functions vs Regular Functions
Arrow functions don't have their own "this" or "arguments" binding. Instead, those identifiers are resolved in the lexical scope like any other variable.
That means that inside an arrow function, "this" and "arguments" refer to the values of "this" and "arguments" in the environment the arrow function is defined in (i.e. "outside" the arrow function)
// Example using a function expression
function createObject() {
console.log('Inside `createObject`:', this.foo);
return {
foo: 42,
bar: function() {
console.log('Inside `bar`:', this.foo);
},
};
}
createObject.call({foo: 21}).bar(); // override `this` inside createObject
// Inside `createObject`: ?
// Inside `bar`: ?
// Example using a arrow function
function createObject() {
console.log('Inside `createObject`:', this.foo);
return {
foo: 42,
bar: () => console.log('Inside `bar`:', this.foo),
};
}
createObject.call({foo: 21}).bar(); // override `this` inside createObject
// Inside `createObject`: ?
// Inside `bar`: ?
const argFunction = function () {
console.log('arguments', arguments);
}
const argArrow = () => {
console.log('arguments', arguments);
}
console.clear();
argFunction(1, 2, 3, 4) // ?
argArrow(1, 2, 3, 4) // ?
Arguments
// Function expresssion are constructable
const Person = function (name, age) {
this.name = name;
this.age = age
}
const person = new Person('Samuel', 28)
// Arrow Functions are not constructable.
const PersonArrow = (name, age) => {
this.name = name;
this.age = age;
}
const personArrow = new PersonArrow('Samuel', 28)
console.clear();
console.log(person) // ?
console.log(personArrow) // ?
Constructor
Classes
JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript's existing prototype-based inheritance.
The class syntax does not introduce a new object-oriented inheritance model to JavaScript.
class Person {
constructor(name, age) {}
}// old way
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.setName = function(name) {
this.name = name;
}
// new way with classes
class PersonClass {
constructor(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
setFirstName(firstName) {
this.firstName = firstName;
}
get fullName() {
return `${this.firstName} ${this.lastName}`
}
}
const samuel = new Person('Samuel', 28);
const samuelClass = new PersonClass('Samuel', 'Castro', 28)
samuel.setName('Samuel Castro');
samuelClass.setFirstName('New First Name')
console.log(samuel); // Person {name: "Samuel Castro", age: 28}
console.log(samuelClass); // PersonClass {firstName: "Samuel Castro", lastName: "Castro", age: 28}
console.log(samuelClass.fullName) // New First Name Castrostatic
class MyClass {
static test() {
console.log('testing')
}
}
MyClass.test() // testing
extends
class Person {
constructor(name) {
this.name = name
}
}
class Dev extends Person {
constructor(name, skills) {
super(name);
this.skilss = skills
}
}
const samuel = new Dev('Samuel', ['js', 'react', 'etc'])
console.clear();
console.log(samuel) // Dev {name: "Samuel", skilss: Array(3)}
console.log(samuel instanceof Dev) // true
console.log(samuel instanceof Person) // true
Destructuring Assignment
The destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables.
let a, b, rest;
[a, b] = [10, 20];
console.log(a); // 10
console.log(b); // 20
[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(rest); // [30,40,50]
Arrays
const {c, d} = {c: 30, d: 40};
console.log(c); // 30
console.log(d); // 40Objects
Functions
const testArray = ([,, name]) => console.log(name);
const testObject = ({a: {b: {c: d}}}) => console.log(d);
const object = {
a: {
b: {
d: 'testD',
c: 'testC',
}
}
}
testArray(["Samuel", "Daniel", "Test"]); // ?
testObject(object); // ?
Spread/Rest Operator
...
Spread syntax allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.
Rest parameter syntax allows us to represent an indefinite number of arguments as an array.
const doSomething = (a, ...b) => { // rest operator
console.log(a);
console.log(b);
}
doSomething('add', 1, 2, 3);
// a = 'add' (string)
// b = [1, 2, 3] (array)
const add = (a, ...b, c) => {}
// SyntaxError: Rest parameter must be last formal parameterRest
Spread
const add2 = (...numbersToAdd) => { // This is a Rest parameter
return numbersToAdd.reduce((sum, next) => sum + next);
}
const numbers = [1, 2, 3];
const result1 = add2(...numbers); // this is a Spread operator
// The above is functionally the same as:
const result2 = add2(1, 2, 3);
console.log(result1); // 6
console.log(result2); // 6const fruits = ['apple', 'orange'];
const allFruits = ['strawberry', ...fruits, 'watermelon'];
// ["apple", "strawberry", "apple", "orange", "watermelon"]const arr = [1, 2, 3];
const arr2 = [...arr]; // like arr.slice()
arr2.push(4);
// arr2 becomes [1, 2, 3, 4]
// arr remains unaffectedconst arr1 = [0, 1, 2];
const arr2 = [3, 4, 5];
// concat
arr1 = arr1.concat(arr2);
// spread
arr1 = [...arr1, ...arr2]Array Literal
Copy Arrays
Concatenate Arrays
const obj1 = { foo: 'bar', x: 42 };
const obj2 = { foo: 'baz', y: 13 };
const clonedObj = { ...obj1 };
// Object { foo: "bar", x: 42 }
const mergedObj = { ...obj1, ...obj2 };
// Object { foo: "baz", x: 42, y: 13 }
Objects
const a = {test: 'ok'};
const b = a
const c = {...a}
console.log(a === b); // ?
console.log(a === c); // ?Spread will create a new object
const a = {
name: 'samuel'
};
const b = a;
const c = b;
const d = c;
const e = d;
const f = {...e};
e.name = 'daniel';
console.log(a); // ?
console.log(e); // ?
console.log(f); // ?What's the value of a, e and f and why?
function todoApp(state = initialState, action) {
switch (action.type) {
case SET_VISIBILITY_FILTER:
return { ...state, visibilityFilter: action.filter }
default:
return state
}
}Spread Operator and React Reducers
Immutability vs Mutability
But Why?
- Mutability will break time-travel on reducer
- React Redux connect function checks to see if the props returned from a mapStateToProps function have changed in order to determine if a component needs to update. To improve performance, connect takes some shortcuts that rely on the state being immutable, and uses shallow reference equality checks to detect changes. This means that changes made to objects and arrays by direct mutation will not be detected, and components will not re-render.
Takeaway
- ECMAScript is a specification that standardize the JavaScript language.
- ES2015, ES2016, ES2017 introduces a lot of new concepts like: arrow functions, classes, spread operators, destructuring assignment, async/await, etc.
- Arrow Function is a shorthand way of declaring functions.
- Arrow Function does not take its own "this" context.
- Classes are primarily syntactical sugar over JavaScript's existing prototype-based inheritance.
- Destructuring assignment is an easy and smart way to assign values to variables.
- Rest/Spread operator is amazing.
- Spread operator will create a new brand cloned object.
- Be aware about how JavaScript object reference work.
- Immutability is important.
- React reducer needs an immutable state to make time-travel work and re-render props as expected.
Upcoming
- Generators
- async/wait (Promises)
- Functional Programming
- Composing functions
- Curry functions
- Ramda - React components with functional programming
- Stateful vs Stateless react components
Questions?
EcmaScript 2016/2017
By Samuel Silva
EcmaScript 2016/2017
- 187