0% found this document useful (0 votes)
5 views230 pages

SEASON-5

JavaScript is a high-level, dynamic, and interpreted programming language that serves as the native language for the web, defined by the ECMAScript standard. It supports various programming paradigms and is widely used across client-side, server-side, and mobile applications. The document covers fundamental concepts such as data types, functions, scope, and arrays, providing insights into JavaScript's capabilities and features.

Uploaded by

Dan Iel
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views230 pages

SEASON-5

JavaScript is a high-level, dynamic, and interpreted programming language that serves as the native language for the web, defined by the ECMAScript standard. It supports various programming paradigms and is widely used across client-side, server-side, and mobile applications. The document covers fundamental concepts such as data types, functions, scope, and arrays, providing insights into JavaScript's capabilities and features.

Uploaded by

Dan Iel
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 230

1.

JavaScript Fundamentals
1.2

What is JavaScript?
High-level, dynamic, weakly typed, prototype-based, multi-paradigm, and
interpreted programming language
...but more importantly...

It is the native programming language for the web


1.3

JavaScript
High-level, dynamic, weakly typed, prototype-based, multi-paradigm, and
interpreted programming language
It is deployed as source code and it is an essential part of the Web platform

AKA ECMAScript, ECMA-262, ES


1.4

ECMAScript
International standard that defines JavaScript
Developed by Technical Committee 39 (TC-39)
Issued as Ecma-262 and ISO/IEC 16262

Each browser vendor provides its own implementations of the standard!

JavaScript Engines
1.5

A Brief History of JavaScript


The first JavaScript engine was created in 10 days by Brendan Eich at
Netscape for the Netscape Navigator Web browser
The engine was code-named SpiderMonkey, implemented in C and still used in Firefox newest Quantum browser

A Brief History of JavaScript, by Brendan Eich


A Brief History of JavaScript, Auth0
1.6

Platform built on Chrome's V8 JavaScript engine and using an event-


driven, non-blocking I/O model that makes it lightweight and efficient

Designed to build fast and scalable network applications

HTTP is a first class citizen, making it well suited


for the foundation of a web library or framework

Node.js package ecosystem, npm, is the largest ecosystem


of open source libraries in the world
1.7

Ubiquitous JavaScript
Client Side
Server Side
Mobile
Desktop
Database
Web APIs
1.8

The Good and the Bad


Good Stuff Bad Stuff
Implied globals
First-class Functions
Function scope
Closures
Complex this binding
Prototypes
Aggressive type coercion
Object literals
Falsy values
Array literals
... many more ...
1.9

JavaScript is incredibly expressive


The expressiveness of JavaScript provides an
enormous amount of power. Even though the
language lacks certain useful built-in features, its
flexibility allows you to add them yourself...
Ross Harmes, Dustin Diaz in Pro JavaScript Design Patterns
1 . 10

JS Fu*k
It is possible to write any JavaScript code with only 6 chars
1 . 11

{ Exercise }
Development Environment Setup

Google Chrome

Visual Studio Code

Node.js
2.1

Introduction to JavaScript
Many people start writing JavaScript
without taking the time to learn the language...

... but when you need to know what you are doing!
2.2

Data Types
2.3

Primitive Data Types


A primitive value is an immutable piece of data that is
represented directly at the lowest level of the language implementation
Type Values Size Comments
Undefined undefined used when a variable has not been assigned a value
value that represents the intentional absence of any object
Null null
value
Boolean true, false 1 bit
length * 2 finite ordered sequence of zero or more 16-bit unsigned integer
String 'A/C', "A/C"
bytes representing UTF-16 characters
-1.5, -1, -0, 0, +0, 1, 1.5
-1.7976931348623157e+308 double precision 64-bit binary format IEEE 754-2008 value plus
Number 8 bytes
1.7976931348623157e+308 additional symbolic values for infinity and not-a-number
-Infinity, +Infinity, NaN
2.4

{ Add-On }

What Every Programmer Should Know About Floating-Point Arithmetic


Avoiding Problems with Decimal Math in JavaScript
JavaScript library providing simple and advanced number, money and currency formatting
A JavaScript library for arbitrary-precision arithmetic
2.5

Objects
A JavaScript object can be looked at as a simple collection of Properties
Objects implement a Map Data Structure, where properties are containers that hold primitives or other objects

// object literal syntax makes creating objects extremely easy


var obj = { a: 42, b: true, c: { } };

obj.a; // 42
obj.b; // true
obj['c']; // {}

var key = 'd';


obj[key] = 'AC';
obj.d; // 'AC';

Everything that is not a primitive is an Object


This includes Functions and Arrays!
2.6

Property Access
Objects can have properties read or written to, as well as new ones
added or removed dynamically
// 1. Dot syntax
newObject.someKey = "Hello"; // create a new property if non existent and update value
var value = newObject.someKey; // get property value

// 2. Square bracket syntax


newObject["someKey"] = "Hello"; // create a new property if non existent and update value
var value = newObject["someKey"]; // get properties

// 3. Object.defineProperty (ES5 only)


// create a new property if non existent and update attributes and value
Object.defineProperty( newObject, "someKey", {
value: "for more control of the property's behavior",
writable: true,
enumerable: true,
configurable: true
});

// 4. delete property
delete newObject.someKey;
2.7

References
Variables can hold the actual values of primitives types or references to objects

var a = 80; // a holds the value of 80


var b = a; // b holds the value of 80

var a = { n: 80 }; // a holds a reference to the object


var b = a; // b holds a reference to the same object

console.log(a.n); // 80
console.log(b.n); // 80
a.n = 100;
console.log(a.n); // 100
console.log(b.n); // 100
2.8

Dynamic Typing
The type of a variable does not have to be declared and can be
reassigned to a different type
var bootcamp = 10; // bootcamp is a Number
bootcamp = 'Lisbon'; // bootcamp is now a String
bootcamp = true; // bootcamp is now a Boolean
bootcamp = { edition: 10, city: 'Lisbon', running: true }; // bootcamp is now an Object

typeof operator returns a string indicating the type of the value


console.log(typeof bootcamp); // prints object to the console
2.9

Type Coercion
Converting a value from one type to another is called casting when done
explicitly, and coercion when done implicitly
Type Coercion in JavaScript can be magical...
... but also evil, confusing and sometimes a really bad idea!
2 . 10

Function Declarations
In JavaScript, functions are ordinary objects with the
additional capability of being callable

function foo() {
return 42; function foo(a) {
} console.log(a + 1, arguments);
return 2;
function baz() {} }

foo.bar = "hello world"; // Can you guess what is the output?


foo();
typeof foo; // "function" foo(1);
typeof foo(); // "number" foo('ey');
typeof foo.bar; // "string" var b = foo(1,2,3);
typeof baz(); // "undefined" console.log(b);

The typeof operator doesn't always returns the type No checking is done on either the type or the number
of arguments passed into a function
A function that returns nothing is equivalent to The variable arguments is an array like object
returning undefined containing all passed arguments into the function
All argument passing is done by value, you can pass-
by-value a primitive or a reference to an object
2 . 11

Function Arguments
The arguments object is a local variable available within all
functions
Contains a numerical property for each argument passed to the function
function myFunction(x, y) {
console.log(x);
console.log(y);

for (var i = 0; i < arguments.length; i++) {


console.log(arguments[i]);
}

console.log(arguments['0']);
console.log(arguments.0);
}

// what will happen?


myFunction(1, 2, 3, 4);
2 . 12

Primitive Wrappers
Primitives are immutable and have no methods, but JavaScript has the
Boolean, Number and String objects that wrap around primitive values
var str = 'this is a string primitive';
typeof str; // 'string'

// due to implicit coercion of string to a wrapper object,


// we can invoke methods on it
console.log(str.toUpperCase());

// the new operator is the way to instantiate wrapper objects


var strObject = new String(str);
typeof strObject; // 'object'

var strPrimitive = strObject.valueOf();


typeof strPrimitive; // 'string'

Wrapper objects are immediately destroyed after their use!


3.1

The region of the program where a binding between


a variable and its name is valid
3.2

Lexical Scope
JavaScript has support for static lexical scope only
Variable scope depends on its position on the source code
// a global definition of animal
var animal = 'Horse, ';

function mammal() {

// a local animal variable


var animal = 'Dog, ';

mammal();
animal += ' a mammal with four legs';

// Dog or Horse?
console.log(animal);

Variables in JavaScript can have either Global or Local scope


3.3

Local Scope
Local variables exist only within the function body
of which they are defined
console.log(dog); // bad things will happen

function animal() {

var dog = 'Dob'; // accessible inside animal function only

Please note that contrary to other programming languages, ES5 local scope is bound to function and not block!
3.4

Global Scope
Global variables live through the entire execution of the runtime
and can be accessed and altered in any scope
var dog = 'Dog'; // global definition of dog

function animals() {

console.log(dog); // access to global dog


badAnimal();
console.log(rabbit); // access to global rabbit
}

function badAnimal() {

rabbit = 'rabbit'; // rabbit leaked into the global scope


}

Variables defined outside a function or without the var keyword will be bound to the Global Scope

ES5 contains a strict mode, causing the interpreter to check and scream at evil things such as implicit globals
3.5

Global Objects
Contrary to other programming languages, JavaScript does not have a
standard library, but it does come with a few built in objects available
var date2 = new Date('December 17, 2017 03:24:00');
var date 1 = new Date.now(); // time in milliseconds since the UNIX epoch

var func = new Function('console.log(\'A/C\');');


func(); // prints A/C in the console

new RegExp('^a.*c$').test('abasdfffc'); // true


/^a.*c$/.test('abasdfffc'); // equivalent literal notation

Math.ceil(Math.random() * 10); // calculates a random number between 1 and 10

var obj1 = { a: '1'};


var obj2 = { b: '2'};
var merge = Object.assign(obj1, obj2); // { a: '1', b: '2'}
3.6

Hoisting
Variable declarations are always processed before any code is executed

// global animal variable // global animal variable


var animal = 'dog'; var animal = 'dog';

function showAnimal() { function showAnimal() {

if (animal != 'cat') { var animal; // declare variable


if (animal != 'cat') {
console.log(animal);
console.log(animal);
// declare and assign variable animal = 'cat'; // assign variable
var animal = 'cat'; console.log(animal);
}
console.log(animal); }
}
} // what about now?
showAnimal();
// can you guess the output?
showAnimal();
4.1

High Order Functions


Functions that operate on other functions, either by taking them
as arguments or by returning them, are called higher-order functions
// build a multiplier by 2 and store it
// in the variable named double
var double = multiplier(2);

// use it to double some numbers


console.log(double(5)); // 10
console.log(double(3)); // 6

// builds a new multiplier


function multiplier(operand1) {
return function(operand2) {
return operand1 * operand2;
}
}

Remember that functions in javascript are just ordinary objects


4.2

Function Expressions
Functions can be used before they are declared
due to function declaration hoisting
foo(); // prints bar to the console

function foo() {
console.log('bar');
}

Function expressions are not hoisted


and can not be used before declaration

// bad things happen var foo; // undefined


foo(); foo(); // bad things happen

var foo = function() { foo = function() {


console.log('bar'); console.log('bar');
} }
4.3

IIFE
A function expression can be invoked immediately,
many times useful to avoid global scope pollution
// This function will execute immediately
// extra parentheses are required to tell the interpreter
// this is a function expression and not a declaration
(function() {
var name = 'sting';
})();

console.log(name); // not available


5.1

Arrays
Powerful high-level list-like objects, containing
methods to perform traversal and mutation operations
// array literal syntax is built in the language
var arr = [ 'hello world', 42, true, { a: 1 } ];

arr[0]; // 'hello world'


arr[1]; // 42
arr[2]; // true
arr[3]; // { a : 1 }
arr.length; // 4

typeof arr; // 'object'

arr[999] = null;
arr.length; // 1000
typeof arr[10]; // 'undefined'

Neither the length of an array nor the types of its elements are fixed
5.2

Data Structures with Arrays


Objects and Arrays are so powerful that a Collections library is rarely needed

Arrays can be used as a stack... ...or as a queue


var stack = []; var queue = [];
stack.push(1); queue.push(1);
stack.push(2); queue.push(2);
stack.push(3); queue.push(3);

stack.pop(); // 3 queue.shift(); // 1
stack.pop(); // 2 queue.shift(); // 2
stack.pop(); // 1 queue.shift(); // 3
stack.pop(); // undefined queue.shift(); // undefined

shift and unshift also work pop and unshift also work

Arrays contain their own sort method,


just provide them with a compare function!
5.3

Array Operations
An array can be populated ...and a String generated
with contents from a String... from the elements of an Array
var sentence = 'JavaScript is a lot of fun!'; var numbers = [1, 9, 7, 4];
var words = sentence.split(' '); var year = numbers.join();

console.log(words[5]); // 'fun!' console.log(year); // '1974'

A shallow copy of an array portion ...or elements can be added or


can be created... removed from it
var animals = ['ant', 'bison', 'camel', 'duck', 'elephant']; var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];
animalsSlice = animals.slice(2, 4); myFish.splice(2, 1);
console.log(animalsSlice); // ['camel', 'duck']
console.log(animals); // has not been changed console.log(myFish);
5.4

Array Iteration
var words = ['JavaScript', 'Bootcamp', 'Fun', 'Games'];

// you can break early from a for loop


for (var i = 0; i < words.length; i++) {
if (words[i] === 'Fun') {
break;
}
console.log(words[i] + ' has ' + words[i].length + ' letters.');
}

// improved readability, but not possible to break early


words.forEach(function(word) {
console.log(word + ' has ' + word.length + ' letters.');
});

It is possible to iterate on an object by obtaining an array with its keys


var obj = { a: 1, b: 2, c: 3};

Object.keys(obj).forEach(function(key) {
console.log('Value of key ' + key + ' is ' + obj[key]);
});
5.5

Functional Style with Arrays


The functional style can make code much cleaner and easier to
maintain, although some performance penalty is paid
// apply a filter function to an array, obtaining the older persons
var persons = [{ name: 'Rui', age: 43 }, { name: 'Pedro', age: 29 }];
var old = persons.filter(function(person) {
return person.age > 40;
});

// apply a transform function to an array, transforming each element in the array into its square root
var numbers = [1, 4, 9];
var roots = numbers.map(Math.sqrt); // [1, 2, 3]

// reduce an array to one single value, the total number of characters in the array
var animals = ['cat', 'dog', 'fish'];
var letters = animals.reduce(function(sum, word) {
return sum + word.length;
}, 0); // 10

// most array functions can be chained together, this example flattens an array and finds even numbers
const data = [[1,2,3], [4,5,6], [7,8,9]];
const evens = data.reduce(function(total, value) {
return total.concat(value);
}, []).filter(function(value) {
return value % 2 === 0;
});

The original array objects are not mutated by map, filter or reduce
6

{ Exercise }
✓ you should get a green check mark on all tests
1.1

JavaScript
Frontend Web
Development
1.2

The Web Platform


1.3

World Wide Web


A web of hypertext documents to be viewed by
browsers using a client-server architecture Tim Berners Lee
1.4

Modern Web
The modern Web brought us a plethora of new technologies, such as:
CSS to describe the appearance or presentation of content on a webpage
JavaScript, the programming language that runs in the browser and can add interactivity and other dynamic features to
web applications
Web APIs, used to perform a variety of tasks, such as manipulating the DOM, playing audio or video, or generating 3D
graphics
AJAX, used to fetch data from a server without having to do a full page refresh
WebRTC, enabling audio/video streaming and data sharing between browser clients
2.1

Document Object Model


2.2

Document Object Model


Language neutral interface that allows dynamic access
and update to the contents, structure and style of web pages

It is an object oriented representation of the web page and can be modified with JavaScript
2.3

DOM Tree
In the DOM, documents assume a tree structure of nodes
Browsers use layout engines such as
Webkit (Safari), Blink (Chrome) or Gecko
(Firefox) to parse HTML into a DOM and
render it on screen

These engines historically implemented the DOM standards to varying


degrees of compliance, causing inconsistencies in the way the DOM is
accessed in different browsers
2.4

How do I access the DOM?


The window object represents a browser window containing a DOM
The document property points to the DOM loaded in that window
<html>
<head>
<script>
// create a couple of elements in an empty HTML page
window.onload = function() {
var heading = document.createElement("h1");
var heading_text = document.createTextNode("Academia de Código");
heading.appendChild(heading_text);
document.body.appendChild(heading);
}
</script>
</head>
<body>
</body>
</html>

The window.onload method receives as argument a function callback to be invoked when the document is loaded into the
browser window. The DOM may not fully populated before that!
2.5

DOM Objects
In the DOM API, each HTML element is represented by an object
Each object has various properties and methods that correspond to the
appearance or behavior of the corresponding HTML element

Each object can have parents, children and siblings


2.6

The Document Object


The document node represents the HTML document itself and it is at the
root of the DOM tree
It provides methods for creating new nodes in the document as well as
searching for existing ones
document.createElement(name) - create an element of the given tag name
document.getElementById(id) - get the element with the given id
document.getElementsByClassName(class) - get a list of elements for the given class name
document.getElementByTagName(name) - get a list of elements for the given tag name

var elem = document.getElementById("hello");


<p id="hello">Hello world!</p>
2.7

Create content on the DOM


Starting with a basic HTML table:
<table id="users-table">
<tr>
<th>Name</th>
<th>Email</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</table>

This is what is required to populate it with users data:


// get the table's DOM object
var usersTable = document.getElementById('users-table');

// create a new table row, added to the end of the table


var row = usersTable.insertRow(-1);

// modify the table row HTML


row.innerHTML = htmlStr;
2.8

Traversing the DOM


After retrieving a DOM element, there are a number of properties that
can be used to get elements from elsewhere in the tree
element.parentNode - Returns the parent node of the given element
element.childNodes - Returns a collection of child nodes of the given element
element.firstChild - Returns the node’s first child in the tree, or null if the node is childless
element.lastChild - Returns the node’s last child in the tree, or null if the node is childless
element.nextSibling - Returns the node immediately following the specified one in its parent’s childNodes list, or null if
the specified node is the last node in that list
element.previousSibling - Returns the node immediately preceding the specified one in its parent’s childNodes list, null
if the specified node is the first in that list
2.9

Element Attributes
Most HTML attributes of an element can be accessed through the object
property of the same name
var elem = document.getElementById("logo_image");
console.log("The URL of this image is: " + elem.src);

// replace the old logo on the page with a new one


elem.src = "../img/new_logo.jpg";

// apply some CSS to the new logo


elem.style = "max-height: 50px; border: 1px solid"
2 . 10

Element Contents
Element contents can be retrieved or changed
element.innerHTML - This property represents the HTML within the element
element.textContent - This property represents the plain text within the element. This is equivalent to the inner HTML,
but with all the tags stripped out

var button = document.getElementById('submit');


button.textContent = 'DO NOT PRESS!!!';
2 . 11

{ Exercise }
Head to www.google.com and apply some creative CSS and
content to the logo and sign-in button
2 . 12

Events
The DOM provides methods for registering and
unregistering event listeners on elements
EventTarget is an interface implemented by DOM nodes that can receive
events and may have listeners for them
element.addEventListener(type, callback, options) - Register an event handler of a specific event type on the EventTarget
element.removeEventListener(type, listener, options) - Removes an event listener from the EventTarget
element.dispatchEvent(event) - Dispatch an event to this EventTarget

var helloWorldFn = function() {


console.log("hello world!");
};

var btn = document.getElementById("hello_world_btn");


btn.addEventListener("click", helloWorldFn, false)
2 . 13

Event Default Action


Many events have a default action
Clicking on a hyperlink will make the browser navigate to the target page by default

Clicking on a form submission button will cause the browser to submit the form to the server by default

If there is an event listener attached to an element, the event listener will


fire first before the default browser action is run.
var preventDefault = function(event) {
event.preventDefault()
};

var link = document.getElementById("disabled_link")


link.addEventListener("click", preventDefaultFn, false);

The event listener can choose to prevent the action from being run
2 . 14

Event Propagation
When an event is fired, the element’s event handlers are first fired.
The element’s parent’s event handlers are fired next.
That element’s parent’s event handlers are also fired, and so on, until the
dom root element ( document) is reached

This behaviour is called Event Bubbling

When an event handler is fired, it has an opportunity to stop the event from propagating to its parent. To do so, the
handler can call event.stopPropagation() method on the event object
2 . 15

{ Exercise }
List Customer data using the DOM API

var customerData = [
{"id":1,"firstName":"Rui","lastName":"Ferrão","email":"[email protected]","phone":"777888"},
{"id":2,"firstName":"Sergio","lastName":"Gouveia","email":"[email protected]","phone":"777999"},
{"id":3,"firstName":"Bruno","lastName":"Ferreira","email":"[email protected]","phone":"777666"},
{"id":4,"firstName":"Rodolfo","lastName":"Matos","email":"[email protected]","phone":"777333"}
];
3.1

AJAX
3.2

AJAX
Asynchronous JavaScript and XML refers to a technique for creating
better, faster and more interactive client-side web applications
JavaScript for interacting with the browser
and responding to events
The DOM for accessing and manipulating
the structure of the HTML page
XML, which represents the data exchanged
between the server and client
An XMLHttpRequest object for
asynchronously exchanging data between
the client and the server
Not a technology in itself, AJAX refers to
a variety of technologies coming together
3.3

XMLHttpRequest
The XMLHttpRequest object provides the API to make AJAX requests,
using a variety of formats within a JavaScript application.
var ajax;

if (window.XMLHttpRequest) {
// Mozilla, Safari, IE7+ ...
ajax = new XMLHttpRequest();
} else if (window.ActiveXObject) {
// IE 6 and older
ajax = new ActiveXObject('Microsoft.XMLHTTP');
}

// run this when the ajax request completes


ajax.onreadystatechange = function() {
if (ajax.readyState === 4 && ajax.status === 200) {
alert(ajax.responseText);
}
};

// start the AJAX request


ajax.open('GET', 'http://localhost:8080/api/users', true);
ajax.setRequestHeader('Content-type', 'application/json');
ajax send();
3.4

{ Exercise }
Fetch Customer data with AJAX
Load the customers from the JavaBank REST API
using the XMLHttpRequest object
1.1
1.2

jQuery 101
jQuery is a fast, small, and feature-rich JavaScript library.
It's designed to ease HTML DOM manipulation, event handling,
animation, and AJAX Http requests, with a simple API that works
across the various browsers.
1.3

jQuery Usage
Adding the jQuery library to an HTML page using a CDN:
<head>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js">
</script>
</head>

The jQuery library exposes itself on the global scope


The library can be used through the jQuery property or
with the commonly used $ alias
// define a callback function to run when the dom is ready
$(document).ready(function() {
// ...
});
1.4

DOM manipulation ...with jQuery


The jQuery API makes it really easy to do
cross-browser DOM manipulation
// fetch element by id
var element = $('#id');

// fetch elements by class name


var elements = $('.className');

// fetch elements by tag type


var elements = $('p');

// fetch elements where the id attribute contains str


var elements = $('[id*=str]');

var element = '<tr>'+ '<td>table entry</td>' + '</tr>';

// create the new element and append it to every node with the given class name
$(element).appendTo('.className');

// specify a click event callback function for every button


$('button').click(function(event){
...
});
1.5

{ Exercise }
jQuery DOM manipulation
Substitute all DOM API manipulation on customer data exercise
with jQuery
1.6

AJAX ...with jQuery


Cross-browser AJAX requests are much simpler to achieve with the
jQuery API

function successCallback(response) { // perform an ajax http post request


// do something with the data $.ajax({
} url: 'http://localhost:8080/api/user',
type: 'POST',
function errorCallback(request, status, error) { data: JSON.stringify({
// do something with the error username: 'ferrao'
} password: 'master',
email: '[email protected]'
// perform an ajax http get request }),
$.ajax({ async: true,
url: 'http://localhost:8080/api/users', contentType: 'application/json',
async: true, success: successCallback,
success: successCallback, error: errorCallback
error: errorCallback });
});
1.7

{ Exercise }
AJAX with jQuery
Replace XMLHttpRequest with jQuery
2.1

The web’s most popular front-end template


Use as a foundation for bootstraping your HTML 5 project with
sensible and smart defaults
2.2

{ Exercise }
jQuery CRUD
1.1

JavaScript Deep Dive


1.2

JavaScript Engines
Runtime engines consist of two main components:

Heap is a large region of memory where objects are allocated


Call Stack forms a stack of frames as functions are invoked
1.3

Call Stack
All JavaScript code runs within the scope of
what is known as an Execution Context

A global execution context is created initially and pushed into the call stack
Every time a function is invoked a new execution context is created and pushed into the call stack
Every time a function returns its execution context is popped from the call stack
1.4

Stack Overflow
If the maximum call stack size is exceeded
the program terminates with a RangeError
function foo() {
foo(); // call foo recursively forever
}

foo();
1.5

Code Execution
While executing code, the runtime engine goes through two different
phases multiple times, until there is no more code to run
1. Creation Phase - A new Execution Context gets created
2. Execution Phase - During this phase, the following actions occur:
Created EC is stored in the call stack
Code from the EC is executed
EC is removed from the call stack
Code from the previous EC continues to execute
1.6

Execution Context
It is possible to conceptually represent each execution context (EC)
as an object with three properties
Activation Object stores all variables
defined within the current EC
Scope Chain gives access to the
Activation Object for all parent
lexical scopes
This Binding is a reference to the
object that owns the currently
executing code
1.7

Activation Object
When a function is activated (called), the interpreter scans the function
for arguments and local variables or local function declarations
function foo(x, y) {

var z = 30;

function bar() {}

foo(10, 20);

The result of this scan becomes the Activation object


and is the reason why hoisting occurs
1.8

Scope Chain
Container of Activation Objects for the executing function lexical scope

var oranges = 10;

function printOranges() {
console.log(oranges);
}

function printMoreOranges() {
var oranges = 11;
printOranges();
}

printMoreOranges(); // what is the output?


1.9

this Argument Binding


The implicit this argument is available inside functions
function getOwner() {
console.log(this.owner);
}

var owner = "global";

var obj1 = {
owner: "obj1",
getOwner: getOwner
};

var obj2 = {
owner: "obj2"
};

getOwner(); // "global"
obj1.getOwner(); // "obj1"
getOwner.call( obj2 ); // "obj2"
new getOwner(); // undefined

The value of this is dynamically bound depending on how the function was called!
1 . 10

this Pitfalls
The implicit this binding can produce strange results
// get a collection of all button elements on the page
var buttons = document.getElementsByTagName('button');

for (var i = 0; i < buttons.length; i++) {

buttons[i].onclick = function() {

// log the button pressed to the console


console.log(this.innerText + ' was pressed!');

// make sure every button on page is only pressed once


disableButton();
}
}

function disableButton() {
this.disabled = true;
}

How do you fix this?


1 . 11

Altering this binding


The methods bind, call and apply allow explicit control
over the this argument binding
function compose(prefix, suffix) {
console.log(prefix + this + suffix);
}

// create a new function with a statically set this argument


var compose2 = compose.bind('Rui');
compose2('Hello ', '!');

// call an existing function with an explicitly provided this argument


compose.call('Rui', 'Hello ', '!'); // passing arguments as usual
compose.apply('Rui', ['Hello ', '!']); // passing arguments as an array
1 . 12

Borrowing Methods
JavaScript makes it possible to use one object's method
on a totally different object
The arguments object looks like an array with numerical indexed keys, but lacks all of the array methods

// this blows up, the arguments object lacks the native array methods
function upperCaseArguments() {

return arguments.forEach(function(arg) {
return arg.toUpperCase();
});
}

// this is really smart :)


function upperCaseArguments() {

// invoke the array slice method on top of the arguments object


var argsAsArray = [].slice.call(arguments);

return argsAsArray.map(function(arg) {
return arg.toUpperCase();
});
}
2.1

Closures
2.2

Closures
Accessing variables up the scope chain will make the interpreter
preserve the corresponding EC and create what is called a closure
Closures effectively enable JavaScript asynchronous programming style
addImgClickHandler();

function addImgClickHandler() {
var counter = 0;
var myImage = document.querySelector('img');

myImage.onclick = function() {
counter++;
console.log('You have clicked this image ' + counter + 'times');
}
}

By the time the user clicks the button, the execution of addImgClickHandler has long terminated,
but the counter variable is still accessible
2.3

Explicit Closures
Closures seem complex at first, but they are a powerful tool with many
practical use cases, allowing for creative, expressive and concise code
var twice = multiplier(2);
console.log(twice(5));

function multiplier(factor) {
return function(number) {
return number * factor;
};
}

The AO created upon the execution of multiplier is preserved and available during the execution of twice
2.4

Module Pattern
Closures can be utilized to emulate the concept of classes
with public and private members
var secretFactory = function(secret, key) {

var tries = 3;

return {
get: function(secretKey) {
tries -= 1;
return (tries > 0 && key === secretKey) ? secret : null;
}
};
};

var secret1 = secretFactory('coca-cola recipe', 1234);


var secret2 = secretFactory('a message', 'password');

console.log(secret1.get('1234')); // null
console.log(secret1.get()); // null
console.log(secret1.get('password')); // null
console.log(secret1.get(1234)); // null, secret has been destroyed

console.log(secret2.get('password')); // a message
2.5

Closure Pitfalls
Closures together with lexical scope can produce strange results
var funcs = [];

for (var i = 0; i < 3; i++) {

// push will create new execution context with reference to i


funcs.push(function() {
console.log(i);
});
}

funcs[0](); // 3
funcs[1](); // 3
funcs[2](); // 3

How do you fix this?


3.1

Object Creation
and
Inheritance
3.2

Inheritance
Through inheritance an object gets access to properties and
methods of another object
Classical Inheritance - a class blueprint is required in
order to create an object
Prototypal Inheritance - an existing object can be
used as a prototype for other objects

JavaScript prototypal inheritance is so


flexible that it can emulate
classical inheritance!
3.3

Prototypal Inheritance
Based on a delegation mechanism in which
non existent properties are looked up in prototype objects

var funnyGuy = {
firstName: 'Pedro',
lastName: 'Antoninho'
};

console.log(funnyGuy);
console.log(funnyGuy.valueOf());
console.log(funnyGuy.__proto__.valueOf.call(funnyGuy));

All JavaScript objects delegate to an object


referenced by Object.prototype!
the __proto__ property should not be manipulated directly
3.4

Prototype Link
It is possible to create a new object that delegates to an existing one
var foo = {
a: 42
};

// create bar and link it to foo


var bar = Object.create(foo); // bar.__proto__ = foo
bar.b = 'hello world';

console.log(bar.b); // 'hello world'


console.log(bar.a); // 42 <-- delegated to foo

// shadowing foo.a
bar.a = 2; // hides foo.a
console.log(bar.a); // 2
console.log(foo.a); // 42

Shadowing occurs because properties are only looked up the prototype chain if not present on the object
3.5

Constructor Functions
A constructor function is used to create multiple instances of the
same type of objects, all delegating to a common prototype
function Shape(color, borderThickness) { // roughly the equivalent of performing
this.color = color; // var shape = new Shape('red', 2.0);
this.borderThickness = borderThickness;
} var shape = Object.create(Shape.prototype);
Shape.call(shape, 'red', 2.0);
var shape = new Shape('red', 2.0);

They emulate classes, should only be used with the new operator
and should be capitalized for readability
All functions come with a prototype property that:
references an object that delegates to Object.prototype
contains a constructor property that references the function itself
can be used to expose methods to all objects created from the constructor function
DO NOT confuse the prototype property of a function with the prototype of an object (__proto__)!
3.6

Pseudo-Classical Inheritance
Despite its prototypal nature, classical inheritance can be emulated in
Javascript with constructor functions and the new operator
// Constructor function for objects of type Shape
function Shape(color, borderThickness) {
// property initialization code inside constructor function
this.color = color;
this.borderThickness = borderThickness;
}

// methods inside the prototype property of constructor function


Shape.prototype.show = function() {
console.log(this.borderThickness + ' ' + this.color + ' shape ');
}

var shape = new Shape('red', 2.0); // create a new Shape instance


shape.show(); // 2 red shape
console.log(typeof shape); // object

// check if Shape.prototype is in shape prototype chain


console.log(shape instanceof Shape); // true
Shape.prototype = {}; // set default Shape prototype to an empty object
console.log(shape instanceof Shape); // false
3.7

Subclassing
Subclassing can be achieved in pseudo-classical inheritance
by chaining and linking constructors together
// Animal Constructor
function Animal(name) {
this.name = name;
}
// Animal Methods
Animal.prototype.walk = function() {
console.log(this.name + ' is walking');
}
// Dog Constructor
function Dog(name, breed) {
// chain Animal and Dog constructors
Animal.call(this, name);
this.breed = breed;
}
// Make Dog inherit from Animal by overriding Dog prototype object
// with a new empty object that delegates to Animal.prototype
Dog.prototype = Object.create(Animal.prototype);
// Recreate constructor property destroyed in previous line
Dog.prototype.constructor = Dog;
// Dog Methods
Dog.prototype.bark = function() {
console.log(this.name +
' is from breed' + this.breed +
' and says rauf rauf');
}
4.1

Error Handling
4.2

Errors
When the JS engine encounters an erroneous situation, it's normal flow is
interrupted by doing what is known as throwing an error:
Early Errors - thrown during parsing, can not be handled
Runtime Errors - thrown during execution, can be handled by catching the error

var x = 2; // this line will never be executed


console.log(x);
// this line will trigger an early syntax error
console.log(x + 1;

Syntax errors normally occur early, but sometimes they can occur at runtime as well

var x = 2;
console.log(x); // prints the value 2
// this line will trigger a runtime syntax error
var y = new Function('console.log(x + 1;');
4.3

Error Handling
It is possible to mark a block of statements in the code and
specify a response if an error is thrown at runtime
try {
var myObject = {};
myObject.method(); // throws an error
} catch (err) {
console.log('An error has occurred: ', err);
} finally {
console.log('Error has been handled!');
}
4.4

Error Objects
JavaScript error handling is typically performed through the
generic Error constructor or one of it's subconstructors
try {
var myObject = {};
myObject.method(); // throws an error
} catch (err) {
console.log(typeof err); // object
console.log(err instanceof Error); // true
console.log(err instanceof TypeError); // true
// print a human readable description of the error
console.log(err.name + ': ' + err.message); // TypeError: myObject.method is not a function
if (debug) {
// dump the full stack trace to the console
console.log(err.stack);
}
}
4.5

Error Throwing
An error can be thrown to signal a
runtime error in the execution of the code
The execution of the current function will stop
and control passed to the first catch clause in the call stack
function doSomethingRisky() {
throw new Error('something went wrong...');
}
try {
doSomethingRisky();
} catch (err) {
console.log(err.name); // Error
console.log(err.message); // something went wrong
}

If no catch clause exists, the program will be terminated


4.6

Custom Errors
The Error object can also be used as a base object for custom errors
function CustomError(message, module) {
// Error is not your typical constructor function
var error = Error(message); // chain CustomError and Error constructors
this.name = 'CustomError'; // the standard error name property
this.message = error.message; // the standard message property
this.stack = error.stack; // the stack trace
this.module = module; // the custom module property
}
// Make CustomError inherit from a new error object,
CustomError.prototype = Object.create(Error.prototype);
CustomError.prototype.constructor = CustomError;
try {
throw new CustomError('wrong credentials', 'authentication');
} catch(e){
console.log(e.name + ': ' + e.module + ' - ' + e.message);
console.log(e.stack);
}

Error does not require new and does not manipulate this, it simply returns a new Error instance
5

{ Exercise }
✓ you should get a green check mark on all tests
1

Asynchronous Programming
2.1

Concurrency
JavaScript is a single threaded, concurrent, non-blocking and
asynchronous programming language
2.2

Execution Environment
The JavaScript engine runs inside an execution environment
such as the Browser or Node.js

This environment exposes many APIs to the JavaScript engine, such as


the DOM or XMLHttpRequest (browser) or the Timers (both)
2.3

Concurrency Model
JavaScript has a concurrency model based on an event loop

This model is quite different from models in other languages like C and Java
where concurrency is achieved mainly via parallel code execution using threads
2.4

Event Queue
Browser APIs expose operations that can run concurrently
using a small number of threads
// to be called when data is available
function ajaxCallback() {
console.log(this.responseText);
}
// to be called every 10 ms
function timerCallback() {
console.log('tick');
}
setInterval(timerCallback, 10);
var ajax = new XMLHttpRequest();
ajax.addEventListener('load', ajaxCallback);
ajax.open('GET', 'https://api.github.com');
ajax.send();

Such operations result in a callback function


to be executed by the JavaScript runtime
2.5

Event Loop
When the Call Stack is empty, the Event Loop takes the first
callback from the Event Queue and places it at the top of the Call Stack
for execution

console.log('start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
console.log('end');
// start, end, setTimeout

Each iteration of the event loop is called a tick


2.6

Rendering Engine
Browsers rendering engine executes in the same thread
as the JavaScript runtime
Rendering events have higher priority for execution
and will be fetched from the queue first
// what happens if we run this?
while (true) {}

The event loop will not fetch anything from the queue
if the call stack is not empty
3.1

Callback Functions
A function is called a Callback when it is passed as an argument to
another function for later execution
Callbacks can be invoked synchronously or asynchronously:
// synchronous callback // asynchronous callback
function isOdd(num) { function ring() {
return num % 2; console.log('RING!');
} }
var numbers = [1, 5, 8, 19, 232, 456];
var oddNumbers = numbers.filter(isOdd); setInterval(ring, 1000);

All isOdd callback invocations end The invoking setInterval function ends before the ring
before the invoking filter function ends callback is invoked
3.2

I/O Handling
To handle I/O operations, two different API models exists:
Synchronous and Blocking I/O Asynchronous and Non-Blocking I/O

function doSthWithData(data) { ... } function doSthWithData(data) { ... }


var data = getDataFromServer(); getDataFromServer(doSthWithData);
doSthWithData(data); doSthElse();
doSthElse(); doSthElse();
doSthElse();
3.3

{ Hands On }
HTML Animation
3.4

JSON
JavaScript Object Notation is a lightweight data interchange format
It is based on a subset of JavaScript and widely used in web applications
to exchange data between the client and the server
// a plain js object
var obj = { ticker: 'AAPL', name: 'Apple Inc' };

// serialize an object into a JSON string


var serObj = JSON.stringify(obj);

console.log(typeof obj); // 'object'


console.log(typeof serObj); // 'string'
console.log(serObj); '{"ticker":"AAPL","name":"Apple Inc"}'
console.log(serObj.name); // undefined

// deserialize a JSON string into an object


var deSerObj = JSON.parse(serObj);

console.log(typeof deSerObj); // 'object'


console.log(deSerObj.name); // 'Apple Inc'

Introducing JSON
3.5

AJAX with Browser APIs


Allow loading data from the server without doing a page refresh
window.onload = function() {

fetchData(processResults);

function fetchData(cb) {
var ajax = new XMLHttpRequest();
ajax.addEventListener('load', cb);
ajax.open('GET', 'https://api.exchangeratesapi.io/latest');
ajax.send();
}

// asynchronous callback
function processResults(event) {

var results = JSON.parse(event.currentTarget.response);


var usd = results.rates.USD;

var container = document.getElementById('rate');


container.innerHTML = '<p>1 EUR = ' + usd + ' USD</p>';
}
}
3.6

AJAX with jQuery


The jQuery library has a full suite of Ajax capabilities available,
which wrap around the browser XMLHttpRequest
$(document).ready(function() {

fetchData(processResults);

function fetchData(cb) {
$.ajax({
url: 'https://api.exchangeratesapi.io/latest',
type: 'GET',
dataType: 'json',
success: cb
});
}

// asynchronous callback
function processResults(results) {
var usd = results.rates.USD;
var container = $('#rate');
container.html('<p>1 EUR = ' + usd + ' USD</p>');
}
});
3.7

Async Error Handling


Handling errors inside async callbacks present some challenges
Stack trace loses all the callback invocation context
It is not possible to catch async callback error
/* this pattern DOES NOT work! */

try {
fetchDataAsync(processResults);
} catch (error) {
// error handling logic
console.log('Caught Error: ', error);
}

function fetchDataAsync(cb) { ... }

function processResults(results) {
throw Error('something went wrong');
}

Application will blow up with Uncaught Error and fetchData call will not be present on stack trace
3.8

Callback Error Handling


A separate error callback or callback error argument is required
to pass error details from inside an async callback
fetchData(processResults);

function fetchData(cb) {
$.ajax({
url: 'https://api.exchangeratesapi.io/latest',
type: 'GET',
dataType: 'json',
success: function(results) { cb(null, results) },
error: function(request, statusText, httpError) { cb(httpError || statusText) }
});
}

function processResults(error, data) {


if (error) {
// error handling
}
// process data
}
3.9

{ Exercise }
AJAX with Error Handling
4.1

Callback Woes
Two very important aspects of synchronous code
for function composition are:
1. They return values - feed the return value from one function straight into the next
2. They throw exceptions - if one function fails, all others in the chain are bypassed until error is handled
try {

var result = func3(func2(funct1()));

} catch (error) {
// handle error
}

With async callbacks we have lost both aspects!


4.2

Callback Headaches
Callbacks in sequence are hard... In parallel they are harder...

var result, temporaryResults = [];


var result;
f1(function(err, result) {
if (err) { /* process error */ return; }
f1(function(err, data) { finished(result);
});
if (err) {
f2(function(err, result) {
// handle error
if (err) { /* process error */ return; }
return;
finished(result);
} });

result = data; f3(function(err, result) {


if (err) { /* process error */ return; }
});
finished(result);
});
var f1 = function(cb) {
f2(function(error, result) { function finished(data) {
if (error) { cb(error); } temporaryResults.push(data);
if (temporaryResults.length === 3) {
f3(function(error, result) {
result = temporaryResults[0] +
cb(null, result); temporaryResults[1] +
}); temporaryResults[2] ;
}) }
}); }

And errors so easy to lose!!!


4.3

Promises
An abstraction built on top of callbacks that gives us back
functional composition and error bubbling in the async world
A Promise object represents the eventual completion (or failure)
of an asynchronous operation and its resulting value
Easy in sequence... Equally as easy in parallel...

var result = f1() var result = Promise.all([f1(), f2(), f3()])


.then(f2) .then(function(results) {
.then(f3) return results[0] + results[1] + results[2];
.catch(function(error) { }).catch(function(error) {
// handle error // handle error
}); });

Un-invert the chain of responsibility:


instead of calling a passed callback, return a promise
4.4

Creating Promises
A promise can be created using a constructor function,
after which it will be in one of the following states:
1. pending - initial state, neither fulfilled nor rejected
2. fulfilled - the operation completed successfully
3. rejected - the operation failed
var promise = new Promise(function(resolve, reject) {

// do some async action, promise is in pending state

if (/* everything ok */) {

resolve(value); // promise will be resolved

} else {

reject(Error(value)); // promise will be rejected

}
});

The constructor receives an async function callback with methods for resolving or rejecting the promise
4.5

Using Promises
A promise is a an thenable object to which callbacks can be
attached
promise.then(function(result) {

// do something with the result

}, function(err) {

// handle the error


});

then takes two optional arguments,


a callback for success and another for failure
Once a promise has been settled, its state can not be altered, but we can always add additional handlers to it
4.6

Promise Chaining
Promises can be chained together to transform values or
run additional async actions one after another
var promise = doSomethingAsync();

promise
.then(doSomethingElseAsync)
.then(doSomethingElseAsync)
.then(doSomethingElseAsync, handleSpecificError)
.then(doSomethingElseAsync)
.then(doSomethingElseAsync)
.catch(handleGenericError)
.finally(alwaysRunThis);

Both specific and generic error handling callbacks can be attached to promises
4.7

Parallel Execution
Parallel promises fulfills when all of the promises have fulfilled or
rejects as soon as one of the promises rejects
var promise = Promise.all([
doSomethingAsync(),
doSomethingAsync(),
doSomethingAsync().catch(handleSpecificError,
doSomethingAsync(),
]).catch(handleGenericError);

It fulfills with an array of the values


and rejects with the reason from the first promise that rejected
4.8

Redundant Promises
It is possible to settle a promise as soon as one of many
promises settles
var promise = Promise.race([
doSomethingAsync(),
doSomethingAsync(),
doSomethingAsync().catch(handleSpecificError,
doSomethingAsync(),
]).catch(handleGenericError);

Used when interested only in one of the results


4.9

Advanced Async Flows


Complex async flows can be achieved with promises

asyncThing1().then(function() {
return asyncThing2();
}).then(function() {
return asyncThing3();
}).catch(function(err) {
return asyncRecovery1();
}).then(function() {
return asyncThing4();
}, function(err) {
return asyncRecovery2();
}).catch(function(err) {
console.log("Don't worry about it");
}).then(function() {
console.log("All done!");
});

blue lines for promises that fulfill or red for ones that reject
4 . 10

Settled Promises
It is possible to create settled promises
without actually performing any async action
function doSomethingAsync() {

if (/* some condition */) {


return new Promise(asyncCallback); // do async operation
}

// make sure we always return a promise, even if no async code has been executed

if (/* other condition */) {


return Promise.resolve(value);
} else {
return Promise.reject(new Error());
}
}

doSomethingAsync().then(onSuccess).catch(onError);

Since a promise is always returned, we can use then and catch callback methods
on the promise return value, which will always be executed in the next event loop tick
4 . 11

{ Exercise }
AJAX with Promises
Use the browser fetchapi to order a list of GitHub users by score

https://developer.github.com/v3/search/
4 . 12

{ Exercise }
✓ you should get a green check mark on all tests
5.1

Single Page Application


Modern web application development paradigm made possible by AJAX
and asynchronous programming
Only one web page is requested from the
server
Each new page is generated dynamically
through JavaScript DOM manipulation
Code is typically organized in separate
JavaScript modules
A Router module allows the creation and
usage of multiple page URLs without page
reloading
5.2

JavaScript Modules
A module is a reusable piece of code that encapsulates implementation
details and exposes public methods so it can be used by other code
Modules should allow us to:
abstract code
encapsulate code
code reuse
manage code dependencies
5.3

Modular JavaScript
Before ES6, no official syntax to define modules existed and developers
were often times forced to choose between:
code their entire application in a single file, which results in a big mess
expose on the global scope some variation of the module pattern
which often lead to namespace collisions
<!--
developers used to write a bunch of script tags with implicit dependencies that had to be
manually ordered and pray for no ordering issues or collisions on the global scope...
-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script src="https://www.google-analytics.com/analytics.js"></script>
<script src="js/main.js"></script>
<script src="js/module1.js"></script>
<script src="js/module2.js"></script>
<script src="js/module3.js"></script>
5.4

Module Systems
Various formats to define modules in JavaScript were developed,
minimizing the lack of native JavaScript module syntax
Some of the most widely adapted and well known formats are:
AMD - Asynchronous Module Definition, an asynchronous module system for the browser
CommonJS - Popular system used by Node, can be used in the browser with tools such as Browserify or Webpack
UMD - Universal Module Definition, supports both AMD and CommonJS modules, both in Node and the Browser
ES6 modules - native javascript modules, supported on newer browsers only
5.5

Asynchronous Module Definition (AMD)


A mechanism for defining and asynchronously loading modules and their
respective dependencies for the browser environment
// Filename: foo.js

// Calling define with a dependency array and a factory function


define(['jquery'], function($) {

// Methods
function myFunc() {
// do something with jquery here...
};

// Exposed public methods


return myFunc;
});
5.6

RequireJS
JavaScript file and module loader supporting the AMD standard
A JavaScript application consisting of multiple modules and their
respective dependencies can be bootstraped with a single script tag:
<!DOCTYPE html>
<html>
<head>
<title>My Web App</title>

<!-- data-main attribute tells require.js to load the js/app.js file after require.js loads -->
<script data-main="js/app"
src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.5/require.min.js"></script>
</head>
<body>
<h1>My Web App</h1>
</body>
</html>
5.7

RequireJS Configuration
A global require object is exposed, which can be used to configure
RequireJS and bootstrap the application
// Filename: js/app.js
require.config({

// path to fetch all our modules from


baseUrl: '/js/app'
});

// set the main module as our application entry point


require(['main'], function() {
console.log('All modules finished loading');
});

// Filename: js/main.js
require(['router'], function(router) {

$(document).ready(function() {
console.log('dom is ready');
router.start();
});
});
5.8

Client Side Routing


The SPA model breaks the browser page history navigation using the
Forward/Back buttons
Both Hash-based routing and the HTML5 History API enable
modifications to the page URL without reloading the page, allowing
creation of separate URLs for different views
5.9

Hash-based Routing
URLs can contain some data prepended with a # character
This data is called the hash fragment

Changes in the hash fragment never trigger a page reload and can be
used for storing the state of the client application
5 . 10

{ Hands On }
Simple JavaScript Router
5 . 11

{ Exercise }
MarvelApp
1.1

Modern JavaScript
1.2

ES6/ES2015
ES6 is not just a modest set of new APIs but a radical jump!
Constants Classes
Scoping Symbol Type
Arrow Functions Iterators
Extended Parameter Handling Generators
Template Literals Map/Set/WeakMap/WeakSet
Extended Literals Typed Arrays
Enhanced Regular Expression New Built-In Methods
Enhanced Object Properties Promises
Destructuring Assignment Meta-Programming
Modules Internationalization & Localization

Despite an impressive set of new features,


ES6 is backwards compatible
ES6 - New Features: Overview & Comparison
1.3

Browser Support
ES6 support varies substantially
across browsers and JS environments

ES6 performance is getting better, but still catching up...


1.4

Use ES6+ syntax without waiting for browser support

Transpiling is the process of compiling


ES6 source code into ES5 source code
1.5

Node Support
ES6 and ES2016(ES7) are already mainstream on Node.js

Node.JS ES2015 support

Node.JS ES2016 support


2.1

Block Scoped Declarations


In ES5, the fundamental unit of variable scoping was the function
var a = 2;
(function iife() {
var a = 3;
console.log(a); // 3
})();

console.log(a); // 2

But in ES6 we can declare variables bounded to any code block


var a = 2;
{
let a = 3;
console.log(a); // 3
}

console.log(a); // 2

No more reason to use function scope, block scoping is the way to go!
2.2

let
let declarations attach to the block scope
{
console.log(a); // undefined
var a = 1;

console.log(b); // ReferenceError thrown


let b = 2;
}

console.log(a); // 1
console.log(b); // ReferenceError thrown

block scoped variables are not initialized until they appear in the block
2.3

let and closures


If used in the header of a for loop,
let will create a new variable binding per loop iteration
var funcs = [];

for (let i = 0; i < 5; i++) {


funcs.push(function() {
console.log(i);
});
}

funcs[1](); // 1
funcs[3](); // 3

Closures created inside the loop iteration


close over each iteration binding
2.4

const
Read-only block scoped variable declaration
{
const a = 2;
console.log(a); // 2

a = 3; // TypeError!
}

If the value of a constant is complex such as an object or an array, the


objects themselfs are mutable
{
const p = { x: 1, y: 0};
p.y = 1; // mutation of the referenced object is not a problem

p = { x: 1, y: 0}; // TypeError thrown


}
3.1

... REST/SPREAD
When used as a function argument, it will gather the rest
of the arguments into an array
function foo(a, ...args) {
console.log(a); // 1
console.log(args); // [2,3,4,5]
}

foo(1, 2, 3, 4, 5);

When used in front of an array it will spread out into its individual values
function foo(a, b, c, d, e, f) {
console.log(a, b, c, d, e, f);
}

const values = [1, 2, 3, 4, 5];

foo(...values); // 1 2 3 4 5

No more need to use the [].slice.call(arguments) hack to convert arguments into an array
3.2

Default Parameter Values


A new syntax exists for setting a default value on a function parameter
// ES5 way
function foo(x, y) {
x = x || 10;
y = y || 30;
return x + y;
}

console.log(foo(5, 6)); // 11
console.log(foo(5)); // 35
console.log(foo(0, 1)); // oops... what is the problem here?

// ES6 way
function bar(x = 10, y = 30) {
return x + y;
}

console.log(bar(5, 6)); // 11
console.log(bar(5)); // 35
console.log(bar(0, 1)); // 1

Much simpler and less error prone


3.3

Destructuring Assignment
Unpacks selected values from arrays, or properties from objects,
into distinct variables
// ES5 style // ES6 style
var results, company, companyDetails; const [company, companyDetail] = Promise.all([
companyService.get(id),
results = Promise.all([ companyService.getDetail(id)
companyService.get(id), ]);
companyService.getDetail(id)
]);
company = results[0];
companyDetails = results[1];

Discarding non interesting properites form objects is easy


function getUser() {
return { name: 'Rui', hobby: 'surf' };
}
let { name } = getUser(); // don't really care about hobbies...
console.log(name);
3.4

Object Enhancements
A number of important convenience extensions
to the object literal exist in ES6
// ES5 // ES6
var color = 'red'; const color = 'red';
var speed = '10'; const speed = '10';
var computedProp = 'hand brake'; const computedProp = 'hand break';

var car = { let car = {


color: color, color,
speed: speed, speed,
start: function() { start() {
console.log('Vruuuum!'); console.log('Vruuuum!');
} },
}; [computedProp]: true
}
car[computedProp] = true;

object enhancements help you write less code


and easily create complex Objects
3.5

Getters and Setters


Syntax to bind an object property to a function to be called
when there is an attempt to get or set the property
let person = {

firstName: 'Rui',
lastName: 'Ferrão',

get fullName() {
return this.firstName + ' ' + this.lastName;
},

set fullName(value) {
[this.firstName, this.lastName] = value.split(' ');
}
};

console.log(person.fullName); // Rui Ferrão

person.fullName = 'Pedro Antoninho';


console.log(person.fullName); // Pedro Antoninho
3.6

Template Literals
String templates provide interpolation,
giving us a lot more control over creating strings
// ES5 // ES6
var name = 'Pedro'; let name = 'Pedro';
var greeting = "Hello " + name + "!"; let greeting = `Hello ${name} !`;

console.log(greeting); // Hello Pedro! console.log(greeting); // Hello Pedro!


console.log(typeof greeting); // string console.log(typeof greeting); // string

A great benefit of interpolated string literals is they are allowed to span across multiple lines

let test = `Blessed is he who, in the name of charity and goodwill,


shepherds the weak through the valley of darkness,
for he is truly his brother's keeper, and the finder of lost children.
And I will strike down upon thee with great vengeance
and furious anger those who attempt to poison and destroy my brothers.`
console.log(text);

The line breaks in the interpolated string literal are preserved in the string value
4.1

Arrow Functions
Shortcut for creating anonymous functions with
this bounded to lexical scope
// How can we fix this? // ES6
let person = { let person = {
name: 'Rui', name: 'Rui',
delayedHello(delay) { delayedHello(delay) {
setTimeout(function() { setTimeout(() => {
console.log(this.name); console.log(this.name);
}, delay); }, delay);
} }
}; };

person.delayedHello(1000); // undefined person.delayedHello(1000); // Hello Rui!

Before ES6 we could solve this using bind to set the this context or grab the context on a closure ( that)
The arguments object is not available with arrow functions, the ...rest operator has to be used instead
4.2

Shorter Syntax
Arrow functions provide for a compact syntax
// ES5 // ES6
var math = { let math = {
product: function(x, y) { product: (x, y) => x * y,
return x * y; square: x => x * x
}, }
square: function(x) {
return x * x;
}
};

we got rid of function brackets and return statement for one liners,
as well as parentheses if the function receives only one argument
5.1

Classes
ES6 Classes are syntactic sugar over prototype-based inheritance
// ES5 // ES6
class Person {
// constructor function
function Person(name, age) { constructor(name, age) {
this.name = name; this.name = name;
this.age = age; this.age = age;
} }

// static method static greet() {


Person.greet = function() { console.log('Hi!');
console.log('Hi!'); }
}
fakeAge(years) {
// instance method return this.age - years;
Person.prototype.getFakeAge = function(years) { }
return this.age - years; }
}
5.2

Subclassing
extends keyword can be used to create a class as a child of another class
class Animal {
constructor(name) {
this.name = name;
}

speak() {
console.log(this.name + ' makes a noise.');
}
}

class Dog extends Animal {


speak() {
console.log(this.name + ' barks.');
}
}

It is now possible to extend natives such as Array or Error


5.3

Default Constructors
A default constructor is created for all classes if omitted
class Animal {

// default constructor for classes


constructor() { }

};

class Dog extends Animal {

// default constructor for subclasses


constructor(...args) {

super(...args);

// this is now available


}
};

In a constructor of a subclass, this cannot be accessed until super is called


6.1

Modules
ES6 introduced a new standardized module format
One module per file
Module API is static
Modules are singletons and mantain state
Importing a module implies a blocking load

The mechanism for module loading is provided by


the hosting environment (browser, node, webpack, etc.)

ES6 module loading is one of the latest feature to arrive to browsers


6.2

Module Exports
The export keyword can be used in front of a declaration
or as an operator with a list of bindings to export
// all API members as named exports

export function add() { } // export add binding


export let multiplier = 100; // export multiplier binding

let odds = [1, 3, 5];


let evens = [2, 4, 6]
let zero = 0;
export { odds, evens }; // export odds and evens bindings
export zero as nil; // export nil as alias to zero binding

// one default export per module


export default function substract() { } // default export

ES6 modules export immutable bindings, not values or references


6.3

Module Imports
The import keyword can be used to load a module from another one
// loads, compiles and evaluates the module without actually importing any of its bindings
import "module";

// import the default export as sub


import sub from 'module';

// import the named exports add and multiplier (aliased to mul)


import { add, multiplier as mul } from 'module';

// import the entire module API to the single math namespace


import * as math from 'module';

import only the specific bindings from a module that are required
6.4

Browser Module Loading


The latest browsers are already supporting module loading
// index.html
<script type="module">
import {addTextToBody} from './utils.js';

addTextToBody('Modules without babel/webpack!!!');


</script>

// utils.js
export function addTextToBody(text) {
const div = document.createElement('div');
div.textContent = text;
document.body.appendChild(div);
}

type=module makes the browser treat the inline or external script as an ES6 module
7.1

Async/Await
Abstraction built on top of Promises/Generators that allows writing
asynchronous code in a readable and synchronous looking fashion
// With ES6 Promises // With ES2017 async/await
function fetchUser(login) { async function fetchUser(login) {

const api = 'https://api.github.com/users'; const api = 'https://api.github.com/users';


const response = await fetch(`${api}/${login}`);
return fetch(`${api}/${login}`) const user = await response.json();
.then(response => response.json())
.then(user => ({ return {
name: user.name, name: user.name,
location: user.location location: user.location
})); };
} }

async functions always return a Promise!


await schedules the execution of the remaining of the function
to when the promise is fulfilled!
7.2

Awaiting asynchronous functions


We can only await on an async function inside another async function
async function sleep(timeout) {
return new Promise((resolve) => setTimeout(resolve, timeout));
}

(async function() {
await sleep(1000); // wait for 1 second
console.log('Done!');
})();

Top level await has to be wrapped in an async IIFE

// non-Promise values are wrapped in a Promise


let value1 = (async () => { return await 42; })();
let value2 = (async () => { return 42; })();

console.log(value1 instanceof Promise); // true


console.log(value2 instanceof Promise); // true

We can await on any thenable or non Promise value


7.3

Sequential Flows
Mutiple promises can be executed sequentially using the await operator
async function fetchGitHub(endpoint) {

const api = `https://api.github.com/${endpoint}`;

const response = await fetch(api);


return response.json(); // return the promise, no need to await
}

async function showRepos(login) {

const user = await fetchGitHub(`users/${login}`);


const repos = await fetchGitHub(`users/${login}/repos`);

console.log(`${user.name} repositories:`);
repos.forEach((repo) => console.log(repo.name));
}

How can the showRepos function be optimized?


7.4

Parallel Flows
The Promise.all method can be used to fire multiple promises in parallel
async function fetchGitHub(endpoint) {

const api = `https://api.github.com/${endpoint}`;

const response = await fetch(api);


return response.json(); // return the promise, no need to await
}

async function showRepos(login) {

const [user, repos] = await Promise.all([


fetchGitHub(`users/${login}`),
fetchGitHub(`users/${login}/repos`)
]);

console.log(`${user.name} repositories:`);
repos.forEach((repo) => console.log(repo.name));
}

As soon as one promise gets rejecteds, Promise.all will reject


7.5

Error Handling
Async functions return a rejected promise when an error is thrown
async function fetchGitHubUser(login) {
const api = `https://api.github.com/users/${login}`;
const response = await fetch(api);
const body = await response.json();

if (!response.ok) {
throw new Error(body.message); // throwing inside async rejects the returned promise
}

return body;
}

try/catch blocks can be used to handle errors in asynchronous functions


async function showGitHubUser(login) {
try {
const user = await fetchGitHubUser(login);
console.log(`${user.name} is from ${user.location}`);
} catch (err) {
console.log(err.message);
}
}
7.6

Looping with async/await


We can use async/await inside regular for loops
async function randomNums(howMany) {
let results = [];
for (let i = 0; i < howMany; i++) {
await sleep(1000);
results.push(Math.random());
}
return results;
}

console.log(await randomNums(10)); // 10 random numbers after 10 seconds

But things do not work quite as expected inside a forEach or other array methods...

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].forEach(async (num) => {


await sleep(1000)
console.log(num)
});

console.log('Finished!');
7.7

{ Exercise }
AJAX with async/await
8

{ Exercise }
✓ you should get a green check mark on all tests
1
2.1

React Core Principles


2.2

User Interfaces
Hard to build because there is so much state
Data changing over time is the root of all evil
2.3

What is React?
A Library for creating User Interfaces
Uses a Virtual DOM that selectively renders subtrees of nodes based
upon state changes
Renders UI and responds to events
People say it is the V in MVC...
I agree the Model is missing
And it is mostly about the View
But my Controller is somewhere in there!
2.4

Separation of Concerns
Design principle for separating a computer program into distinct sections, such that each
section addresses a separate concern

Models are usually plain JavaScript objects

Views are usually implemented using


some sort of HTML template system

Controllers contain view related logic


tightly coupled with Views

Most JavaScript MVC frameworks end up separating by technology and not by concerns!
View and Controllers are tightly coupled, making it difficult to change one without the changing the other
2.5

Separation of Components
React uses Components to separate concerns,
written with the full power of JavaScript.

In React everything is a Component!


2.6

Component Based
React is all about building components, not templates
They split the UI into independent reusable pieces

Components are reusable, composable, maintainable, testable and know how to render themselves into the DOM
2.7

Composition
Just like regular functions, React components can be composed together

This principle is a key feature of React and present at the core of how react applications are developed
2.8

Declarative User Interface


Imperative Programming - sequence of instructions telling the
machine exactly how to do something
Declarative Programming - telling the machine what should happen
and let it work out how to do it
// Imperative jQuery code // Declarative React code to
// to create a header section // create a header section component
function createHeaderSection(text) { function HeaderBlock(props) {
let element = $('<div/>'); return (
let header = $('<h1/>'); <div>
header.text(text); <h1>{props.text}</h1>
element.append(header); </div>
return element; );
} }

Reacts declarative style leads to more readable code and with less bugs
2.9

Unidirectional Data Flow


React implements one-way reactive data flow

Components are rendered as a function of the application state


User events can trigger explicit state mutations
State mutations will re-render components
One way data flow is deterministic, making it easier to predict and reason about state changes and data flows
2 . 10

Virtual DOM
Re-render on every state change seems expensive,
but is fast because it happens on a Virtual DOM.
On every update the following process takes place:
1. New virtual DOM subtree is built
2. Diff between new and old is performed
3. Minimal set of DOM mutations is calculated
4. DOM mutations are queued
5. All updates are executed together in a single batch

The DOM is slow, but React is fast!


2 . 11

The React Way


Components, not templates
Re-render, don't mutate
Virtual DOM is simple and fast
3.1

React Ecosystem
3.2

React Developer Tools


An extension that allows inspection of React component hierarchy
in the Chrome and Firefox Developer Tools

Its easy to inspect component hierarchy of existing React applications


3.3

WebPack
Static module bundler for modern JavaScript applications
Recursively builds a dependency graph that includes every module in the
application and packages them into one or more bundles
3.4

Webpack Configuration
Webpack can be configured around four core concepts:
Entry point indicates which module webpack use to begin building its dependency graph
Output property tells webpack where to emit the bundles
Loaders enable webpack to convert to modules
and process all types of files
Plugins can be used to perform a wide variety of tasks such as optimization and minification
// webpack config uses common.js node modules, not ES6
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist') // absolute path required
},

// module transformations to apply on files


module: {
// loaders to apply if files match the test regex
rules: [
// css-loader: transform all css files in valid modules
// style-loader: add css to dom
{ test: /\.css$/, use: ['style-loader', 'css-loader'] }
]
},

// plugins to be invoked by webpack


plugins: [new HtmlWebpackPlugin({ template: 'public/index.html' })]
};
3.5

{ Hands On }
Webpack Build System
3.6

Requires plugins to perform transformations on code


{
// webpack config file
module: {
rules: [
// Babel webpack plugin
{ test: /\.(js|jsx)$/, exclude: /node_modules/, loader: "babel-loader" }
]
}
}

Babel presets apply a predefined set of plugins


# react dependencies
$ npm install --save react react-dom

# webpack babel dependencies


$ npm install --save-dev babel-core babel-loader babel-preset-env babel-preset-react

{
// babel config in package.json file
"babel": { "presets": ["env", "react"] }
}
3.7

Create React App


Official CLI for creating react applications with no setup

# Execute directly from the NPM registry


$ npx create-react-app my-app

# Run the application in development mode


$ cd my-app
$ npm start
3.8

Axios
Promise based HTTP client for the browser and Node.js
Automatic JSON transforms
XSRF protection
Request canceling
async function getUser() {
try {
const response = await axios.get('/user?ID=12345');
console.log(response);
} catch (error) {
console.error(error);
}
}

Quite popular on the React community and a better alternative to fetch


4.1

React Basics
4.2

React Elements
Immutable object describing what should be rendered to the screen
and containing two main properties:
type - String for DOM node or ReactClass for a react component
props - element attributes
{ {
type: 'div', type: Button,
props: { props: {
className: 'container', className: 'ui primary button',
children: '<Academia de Código_>' children: 'Login'
} }
} }

<!-- DOM Node --> <!-- React Component -->


<div class="container"> <Button className="ui primary button">
&lt;Academia de Código_&gt; Login
<div> </Button>

Elements can be created calling React.createElement(node, props)


Child props can be passed as arguments React.createElement(node, props, child1, child2, ...)
4.3

React Components
A React Component is a function or a class
which accepts input properties and returns a React Element
// Button Component
function Button(props) {
return React.createElement('button', props);
}

React Components can be rendered by calling ReactDOM.render(Component(), node)

// properties to pass to the Button component


const props = { className: 'ui button primary', children: 'Login' };

// create element from Button component


const element = React.createElement(Button, props);

// render element to the root div


ReactDOM.render(element, document.getElementById('root'));

React Components must act like pure functions with respect to their props and do not attempt to change them
4.4

{ Hands On }
Rendering React Components
4.5

JSX
Syntax extension to JavaScript to describe React Elements
Syntactic sugar for React.createElement(component, props, ...children)

// required for jsx // required for createElement


import React from 'react'; import React from 'react';

const type = 'section'; const element = React.createElement('div',


const element = ( { className: 'section',
<div className="{type}"> React.createElement('h1', null, 'I am a component!'),
<h1>I am a component!</h1> React.createElement('h1', null, 'I am a sub title!')
<h2>I am a sub title!</h2> }
</div> );
);

Instead of artificially separating technologies by putting markup and logic in separate files,
React separates concerns with loosely coupled components that contain both
4.6

Inline Styles
The style attribute can be used to style a React component
An object with camelCased properties is used, not strings
// paragraph style object
const pStyle = {
color: 'red'
};

// styled react element


const alertText = <p style={pStyle} />;

// render red paragraph with no CSS


ReactDOM.render(alertText, document.getElementById('root'));

Inline styles are normally used for dynamic computed styles as CSS classes are generally more efficient
4.7

{ Hands On }
Rendering JSX Components
5.1

React Components
5.2

Functional Components
Contain no state and expressed as a single pure function which
accepts a props object and returns a React element
// Declare the React Welcome Component
function Welcome(props) {
return <h2>Welcome {props.name}</h2>;
}

// Instantiate and render a React Element


ReactDOM.render(<Welcome name="Rui" />, document.getElementById('root'));

// Same as above
const element = Welcome({name: 'Rui'});
ReactDOM.render(element, document.getElementById('root'));

Functional components are stateless and pure, for the same props they always return the same element
React components should start with uppercase ( <Welcome />) to distinguish them from regular DOM tags( <div /> )
5.3

Composing Components
Complex UI does not fit in a single function and needs to
be abstracted into reusable pieces, hiding implementation details
JSX makes it really easy to compose components together
function ListItem(props) {
return <li>{props.item}</li>;
}

function Popular() {
return (
<ul>
<ListItem item="JavaScript" />
<ListItem item="Java" />
<ListItem item="Ruby" />
</ul>
);
}

ReactDOM.render(<Popular />, document.getElementById('root'));

When a part of the UI is used several times or is complex enough on its own,
it should be extracted into a reusable component.
5.4

Compositional Components
Wrapper Components can be created using the children property

// compose by passing props down // compose using children


function PrimaryButton(props) { function PrimaryButton(props) {
return ( return (
<button> <button>
{props.icon}{props.text} {props.children}
</button> <button>
) )
} }

// usage: // usage:
<PrimaryButton <PrimaryButton>
icon={IconFile} text="Login" <IconFile/> Login
/> </PrimaryButton>

This technique provides a more robust and flexible way of composing


than passing props down the component hierarchy
Specially useful when components do not know their children ahead of time,
such as generic Modal, Sidebar or Dialog boxes for example.
5.5

Property Typechecking
React includes a property typechecking library to help
catching bugs during development
import PropTypes from 'prop-types';

function ListItem({ item , color }) {


return <li style={color: color}>{item}</li>;
}

ListItem.propTypes = {
item: PropTypes.string.isRequired,
color: PropTypes.string
};

// optional properties should have defaults


ListItem.defaultProps = {
color: 'red'
};

prop types and default values checks are enforced during development but removed from production code
5.6

Lists in React
We can create lists in React using JSX and
plain JavaScript array methods such as map or filter
function ListItem({ item }) {
return <li>{item}</li>;
}

function Popular() {
const languages = ['All', 'JavaScript', 'Java', 'HTML', 'CSS', 'C', 'C++'];
return (
<ul>
{ languages.map(lang => <ListItem key={lang} item={lang} />) }
</ul>
);
}

ReactDOM.render(<Popular />, document.getElementById('root'))}

Array items require special unique key attribute for react to identify items changed, added or removed
Contrary to other JavaScript frameworks, there is no special syntax, its all JavaScript with JSX sugar on top
5.7

Class Components
A Class component can be created by extending from
React.Component
class Popular extends React.Component {
render() {
return (
<ul>
{ languages.map(lang => <ListItem key={lang} item={lang} />) }
</ul>
);
}
}

ReactDOM.render(<Popular />, document.getElementById('root'));

Class components without state can be transformed in functional components


by moving the contents of the render() method into a separate function
The Render method needs to act as a pure function, it should only read state and props and render a UI
5.8

Component State
State allows React components to change their output over time
function ListItem({ item, color }) {
return <li style={{ color }}>{item}</li>;
}

class Popular extends React.Component {


static languages = ['All', 'JavaScript', 'Java', 'HTML', 'CSS', 'C', 'C++'];
state = { selected: 'All' };

selectLanguage(lang) {
this.setState({ selected: lang });
}

render() {
return (
<ul>
{Popular.languages.map(lang => {
let color = lang === this.state.selected ? 'red' : 'black';
return <ListItem color={color} key={lang} item={lang} />;
})}
</ul>
);
}
}

Component state lives in a special state property, explicitly updated by invoking the setState() method
Updating the state causes the component to re-render
5.9

Updating State
Updates to the UI are achieved through state updates,
which are enqueued, batched and delayed by React
class Counter extends React.Component {
state = { value: 0 };

stateUpdateCb() { console.log('New state is ', this.state); }

// new state does not depend on previous state, shallow merge is performed
reset() {
this.setState({ value: 0}, this.stateUpdateCb);
}

// new state depends on previous state, state updater function is recommended


increment() {
this.setState(
prevState => ({ value: prevState.value + 1 }),
this.stateUpdateCb
);
}

render() {
return <h2>{this.state.value}</h2>;
}
}

State updates have to be explicitly triggered through setState(), it is not possible to update this.state directly
5 . 10

Event Handling
Event handlers receive instances of SyntheticEvent,
a cross-browser wrapper around the native events
class Counter extends React.Component {
state = { value: 0 };

stateUpdateCb() { console.log('New state is ', this.state); }

increment = () => {
this.setState(
prevState => ({ value: prevState.value + 1 }),
this.stateUpdateCb
);
};

render() {
return <h2 onClick={this.increment}>{this.state.value}</h2>;
}
}

React events are named using camelCase and not lowercase like DOM events
SyntheticEvent is reused and all properties nullified for performance, making it unusable in asynchronous callbacks
5 . 11

{ Exercise }
Clickable React Counter
5 . 12

{ Exercise }
Popular Programming Languages Clickable Menu
6.1

Component Life Cycle


React components provide special methods for
hooking into the component life cycle
Most life cycle methods follow into one of these categories:

1. Component gets mounted into the DOM


2. Component receives new data
3. Component gets unmounted from the DOM
6.2

Mounting Phase
Component is instantiated and inserted into the DOM

componentDidMount() is the correct place to put any initialization code


such as starting timers or fetching data using AJAX
6.3

Updating
Component is being re-rendered due to changes in props or state

shouldComponentUpdate() can prevent unnecessary re-rendering and boost performance


6.4

Component Re-render
When the rendering process finds a difference in a component
it re-renders the whole subtree
function NothingChanges() {
console.log('Will render one more time...');
return <h3>Nothing changed here...</h3>;
}

class Counter extends React.Component {


state = { value: 0 };

increment = () => {
this.setState(
prevState => ({ value: prevState.value + 1 })
);
};

render() {
return (
<div>
<h2 onClick={this.increment}>{this.state.value}</h2>
<NothingChanges />
</div>
);
}
}
6.5

Unmounting
Component is being removed from the DOM

componentWillUnmount() is where cleanup code such as invalidating timers and canceling ajax requests should go
6.6

{ Exercise }
Popular Programming Languages on GitHub
7.1

Forms in React
HTML form elements such as input, textarea or select,
maintain their state - user input - in the DOM
React provides two different approaches to form handling:
Uncontrolled Components - they work just like traditional HTML
forms, keeping and updating state in the DOM
Controlled Components - form state is managed by React just like
every other piece of state in the application
7.2

Uncontrolled Components
The browser stores and updates the value for each form input element
Whenever the value is needed it has to be pulled from the field
class Form extends React.Component {
handleSubmit = () => {
const value = this.input.value;
// do something with value
};

render() {
return (
<div>
<input type="text" ref={input => (this.input = input)} />
<button onClick={this.handleSubmit}>Sign Up</button>
</div>
);
}
}

The ref attribute receives a callback which is called


with a reference to the DOM node when the component is mounted
7.3

Controlled Components
The React way for doing form handling,
where the React state is the single source of truth
Input values are pushed into form fields using a value from state or props

class Form extends React.Component {


state = { text: '' };

handleChange = event => {


this.setState({ text: event.target.value });
};

handleSubmit = () => {
// do something with this.state.text
};

render() {
return (
<div>
<input type="text" value={this.state.text} onChange={this.handleChange} />
<button onClick={this.handleSubmit}>Sign up</button>
</div>
);
}
}

Every state mutation will have an associated handler function, making it really easy to modify or validate user input
7.4

{ Exercise }
Developer Profile on GitHub
8.1

React Router
Provides a collection of navigational components,
composed declaratively in React applications
Everything is a component in React Router,
which means routing occurs when the app is rendering
In static routing, routes are declared before rendering takes place,
which is exactly the opposite of React Router dynamic routing
8.2

Rendering a Router
The Router receives a single child component
which should render the rest of the application
// use the browser based version
import { BrowserRouter } from 'react-router-dom';

ReactDOM.render((
<BrowserRouter>
<App />
</BrowserRouter>
), document.getElementById('root'));

A history object is available to child components and used to keep track


of the current location and re-render the application when it changes
8.3

Route Matching
A Route component will render its content when
its path prop matches the current location pathname
import { Route } from 'react-router-dom';

// when location = { pathname: '/about' }


<Route path='/' component={Header}/> // renders <Header/>
<Route exact path='/' component={Home}/> // renders null
<Route path='/about' component={About}/> // renders <About/>
<Route path='/contact' component={Contact}/> // renders null
<Route component={Footer}/> // renders <Footer/>

The exact property will make the route match if the path property is exactly equal to the pathname
It makes sense to list a number of possible Routes next to each other,
but a Route component can be used anywhere to render content based on location
8.4

Grouping Routes
Routes can be grouped using a Switch component
<Switch>
<Route exact path='/' component={Home}/>
<Route path='/about' component={About}/>
<Route path='/contact' component={Contact}/>
{/* when none of the above match, <NoMatch> will be rendered */}
<Route component={NoMatch}/>
</Switch>

Switch iterates over its children elements and


renders only the first matching Route
8.5

Path Parameters
It is possible to capture path parameters within a pathname
Named parameters are defined by prefixing : to the parameter name and
accessed through the match.params prop
// route config
<Route path='/users/:id' component={User}/>

// component rendered by route


function User({ match }) (
return <h3>User ID: {match.params.id}</h3>;
);
8.6

Query String
The query string is available through the location.search prop
Any query string library such as the popular qs can be used to parse it
// import the popular qs library
import qs from 'qs';

// route config
<Route path='/users' component={User}/>

// component rendered by route


function User({ location }) (

const queryParams = qs.parse(location.search);

// /users?username=rui
return <h3>User Name: {queryParams.username}</h3>;
);
8.7

Navigation
Special components are required for navigation as
standard anchor tags would cause a page refresh
The Link component updates the URL and
changes the rendered content without reloading the page
// location = { pathname: '/react' }

// renders <a href='/'>Home</a>


<Link to='/'>Home</Link>

// location = { pathname: '/react' }


// renders <a href='/react' className='hurray'>React</a>
<NavLink to='/react' activeClassName='hurray'>React</NavLink>

The NavLink component can be styled when active


8.8

Redirect
Navigation can be forced by rendering a Redirect component
function Admin({token}) {
if (!token) {
return <Redirect to='/login'/>;
}

return <h2>Admin Section</h2>;


}
8.9

{ Exercise }
Code Awards

You might also like