0% found this document useful (0 votes)
7 views154 pages

2 ServerSideJS

The document provides an overview of JavaScript concepts, focusing on classes, functions, and arrays. It explains the structure and usage of classes, the nature of first-class functions, and how to manipulate arrays using methods like findIndex and map. Additionally, it covers the differences between function objects and regular objects, as well as the use of anonymous and arrow functions.

Uploaded by

thiendc24v7x629
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)
7 views154 pages

2 ServerSideJS

The document provides an overview of JavaScript concepts, focusing on classes, functions, and arrays. It explains the structure and usage of classes, the nature of first-class functions, and how to manipulate arrays using methods like findIndex and map. Additionally, it covers the differences between function objects and regular objects, as well as the use of anonymous and arrow functions.

Uploaded by

thiendc24v7x629
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

CT449:

Phát triển ứng dụng web


Bùi Võ Quốc Bảo
(bvqbao@[Link])

Cần Thơ, 2022 1


Credit

● The slides are inspired by the CS193X course created by


Victoria Kirst

2
JavaScript

3
Classes in JavaScript

4
Class
- Classes are one of the features introduced in
the ES6 version of JavaScript
- A class is a blueprint for the object. You can create an
object from the class
- The class as a sketch (prototype) of a house.
+ Contains all the details about the floors, doors, windows,
etc.
+ Based on these descriptions, you build the house.
 House is the object

5
Public methods

constructor is optional,
class ClassName { called automatically each
constructor(params) { time an object is created
...
}
Parameters for the
methodName() {
... constructor and methods are
} defined in the same they are
methodName() { for global functions
...
}
} You do not use the function
keyword to define methods
6
Public methods

class ClassName {
constructor(params) {
...
} Within the class, you must
methodOne() { always refer to other methods
[Link]();
}
in the class with the this.
methodTwo() {
prefix
...
}
}

7
Public fields

class ClassName {
fieldName; // Optional
constructor(params) {
[Link] = fieldValue;
[Link] = fieldValue;
}
methodName() {
[Link] = fieldValue;
}
}

Define public fields by setting [Link] in the


constructor… or in any other function
8
Public fields

class ClassName {
constructor(params) {
[Link] = someParam;
}
methodName() {
const someValue = [Link];
}
}

Within the class, you must always refer to fields with the
this. prefix

9
Private fields/methods

class ClassName {
#privateField // Required
constructor(params) {
this.#privateField = fieldValue;
[Link] = fieldValue;
}
#privateMethodName() {
this.#privateField = fieldValue;
}
}

10
Instantiation

Create new objects using the new keyword:

class SomeClass {
...
someMethod() { … }
}

const x = new SomeClass();


const y = new SomeClass();
[Link]();

11
First-class functions

12
First-class functions

Functions in JavaScript are objects


- They can be saved in variables
- They can be passed as parameters
- They have properties, like other objects
- They can be defined without an identifier (anonymous
function)

(This is also called having first-class functions, i.e. functions in JavaScript are
"first-class" because they are treated like any other variable/object)

13
First-class functions

Functions in JavaScript are objects


- They can be saved in variables
- They can be passed as parameters
- They have properties, like other objects
- They can be defined without an identifier (anonymous
function)

(This is also called having first-class functions, i.e. functions in JavaScript are
"first-class" because they are treated like any other variable/object)

???
14
First-class functions

Functions in JavaScript are objects


- They can be saved in variables
- They can be passed as parameters
- They have properties, like other objects
- They can be defined without an identifier (anonymous
function)

(This is also called having first-class functions, i.e. functions in JavaScript are
"first-class" because they are treated like any other variable/object)

Isn't there like… a fundamental


??? difference between "code" and
"data"? 15
Back to the veeeeery basics

What is code?
- A list of instructions your computer can execute
- Each line of code is a statement

What is a function?
- A labeled group of statements
- The statements in a function are executed when the
function is invoked

What is a variable?
- A labeled piece of data
16
Objects in JS

Objects in JavaScript are sets of property-value pairs:

const bear = {
name: 'Ice Bear',
hobbies: ['knitting', 'cooking', 'dancing']
};

- Like any other value, Objects can be saved in variables


- Objects can be passed as parameters to functions

17
Back to the veeeeery basics

What is code?
- A list of instructions your computer can execute
- Each line of code is a statement

What is a function?
- A labeled group of statements
- The statements in a function are executed when the
function is invoked

What could it mean for a


What is a variable?
- A labeled piece of data
function to be an object,
i.e. a kind of data? 18
Function variables

You can declare a function in several ways:

function myFunction(params) {
}

const myFunction = function(params) {


}

const myFunction = (params) => {


}

19
Function variables

function myFunction(params) {
}

const myFunction = function(params) {


}

const myFunction = (params) => {


}

Functions are invoked in the same way, regardless of how


they were declared:
myFunction();
20
const x = 15;
let y = true;

const greeting = function() {


[Link]('hello, world');
}

"A function in JavaScript is an object of type Function"

21
In the interpreter's memory:

const x = 15;
let y = true;

const greeting = function() {


[Link]('hello, world');
}

"A function in JavaScript is an object of type Function"

22
In the interpreter's memory:

x 15

const x = 15;
let y = true;

const greeting = function() {


[Link]('hello, world');
}

"A function in JavaScript is an object of type Function"

23
In the interpreter's memory:

x 15

const x = 15; y true


let y = true;

const greeting = function() {


[Link]('hello, world');
}

"A function in JavaScript is an object of type Function"

24
In the interpreter's memory:

x 15

const x = 15; y true


let y = true;
greeting ...
const greeting = function() {
[Link]('hello, world');
}

"A function in JavaScript is an object of type Function"


What this really means:
- When you declare a function, there is an object of type
Function that gets created alongside the labeled block of
executable code
25
Function properties

const greeting = function() {


[Link]('hello, world'); “greeting“
}
"function () {
[Link]('hel
[Link]([Link]); lo, world'); }"
[Link]([Link]());

When you declare a function, you create an object of type


Function, which has properties like:
- name
- toString
26
Function properties

const greeting = function() {


[Link]('hello, world');
}
[Link]();  "hello, world“
[Link](); // This is the same as [Link]();
greeting();  "hello, world“

Function objects also have a call method, which


invokes the underlying executable code associated with
this function object

27
Function properties

const greeting = function() {


[Link]('hello, world');
}

[Link]();
greeting();

() is an operation on the Function object (spec)


- When you use the () operator on a Function object, it
is calling the object's call() method, which in turn
executes the function's underlying code
28
Code vs Functions

Important distinction:
- Function, the executable code
- A group of instructions to the computer

- Function, the object


- A JavaScript object, i.e. a set of property-value pairs
- Function objects have executable code associated
with them
- This executable code can be invoked by
- functionName(); or
- [Link]();
29
Note: Function is special

Only Function objects have executable code associated


with them
- Regular JS objects cannot be invoked
- Regular JS objects cannot be given executable code
- I.e. you can't make a regular JS object into a callable
function

const bear = {
name: 'Ice Bear',
hobbies: ['knitting', 'cooking', 'dancing']
};
bear(); // error!
30
Function Objects vs Objects

function sayHello() {
[Link]('Ice Bear says hello');
}

const bear = {
name: 'Ice Bear',
hobbies: ['knitting', 'cooking', 'dancing'],
greeting: sayHello
};
[Link]();

But you can give your object Function properties and


then invoke those properties 31
Function Objects vs Objects

function sayHello() {
[Link]('Ice Bear says hello');
}

const bear = {
name: 'Ice Bear',
hobbies: ['knitting', 'cooking', 'dancing'],
greeting: sayHello
};
[Link]();

The greeting property is an object of Function type


32
Callbacks

Callback: A function that's passed as a parameter to


another function, usually in response to something

Because every function declaration creates a Function


object, we can pass Functions as parameters to other
functions

33
[Link]
- Used to find the index of the first element in an array that
satisfies a given testing function. Returns -1 if no match is
found
- Syntax:
[Link](function(currentValue, index, arr), thisValue)
Parameter Description
function() Required. A function to be run for each array element.
currentValue Required. The value of the current element.
Index Optional. The index of the current element.
Arr Optional. The array of the current element.
thisValue Optional. Default undefined. A value passed to the
function as its this value.
34
[Link]
const flavors =
['vanilla', 'chocolate', 'strawberry', 'green tea'];

function isStrawberry(element) {
return element === 'strawberry';
}

const indexOfStrawberry = [Link](isStrawberry);

The isStrawberry function will fire for each element in


the array

35
[Link]

const flavors =
['vanilla', 'chocolate', 'strawberry', 'green tea'];

function isStrawberry(element) {
return element === 'strawberry';
}

const indexOfStrawberry = [Link](isStrawberry);

36
[Link]

const flavors =
['vanilla', 'chocolate', 'strawberry', 'green tea'];

function isStrawberry(element) { Returns false, so


return element === 'strawberry'; keep searching.
}

const indexOfStrawberry = [Link](isStrawberry);

37
[Link]

const flavors =
['vanilla', 'chocolate', 'strawberry', 'green tea'];

function isStrawberry(element) {
return element === 'strawberry';
}

const indexOfStrawberry = [Link](isStrawberry);

38
[Link]

const flavors =
['vanilla', 'chocolate', 'strawberry', 'green tea'];

function isStrawberry(element) { Returns false, so


return element === 'strawberry'; keep searching.
}

const indexOfStrawberry = [Link](isStrawberry);

39
[Link]

const flavors =
['vanilla', 'chocolate', 'strawberry', 'green tea'];

function isStrawberry(element) {
return element === 'strawberry';
}

const indexOfStrawberry = [Link](isStrawberry);

40
[Link]

const flavors =
['vanilla', 'chocolate', 'strawberry', 'green tea'];

function isStrawberry(element) { Returns true, so


return element === 'strawberry'; stop searching.
}

const indexOfStrawberry = [Link](isStrawberry);

41
[Link]

const flavors =
['vanilla', 'chocolate', 'strawberry', 'green tea'];

function isStrawberry(element) {
return element === 'strawberry';
}

const indexOfStrawberry = [Link](isStrawberry);

findIndex returns 2, since the first element to pass the


testing function was found at index 2
42
Anonymous functions

43
Anonymous functions

We do not need to give an identifier to functions


When we define a function without an identifier, we call it
an anonymous function
- Also known as a function literal, or a lambda function

We can define our test function directly in findIndex:


function isStrawberry(element) {
return element === 'strawberry';
}

const index = [Link](isStrawberry);

44
Anonymous functions

We do not need to give an identifier to functions.


When we define a function without an identifier, we call it
an anonymous function
- Also known as a function literal, or a lambda function

We can define our test function directly in findIndex:


const index = [Link](
function(element) { return element === 'strawberry'; });

45
Arrow functions

We can use the arrow function syntax for defining


functions:

const index = [Link](


function(element) { return element === 'strawberry'; });

46
Arrow functions

We can use the arrow function syntax for defining


functions:

const index = [Link](


(element) => { return element === 'strawberry'; });

47
Concise arrow functions
We can use the concise version of the arrow function:
- You can omit the parentheses if there is only one
parameter
- You can omit the curly braces if there's only one
statement in the function, and it's a return statement
const index = [Link](
(element) => { return element === 'strawberry'; });

const index = [Link](


element => element === 'strawberry');

[Link]
48
Arrow functions and this keyword

An arrow function doesn’t have its own bindings to this or


super, and should not be used as methods

const obj = {
i: 10,
b: () => [Link](this.i, this),
c: function() {
[Link](this.i, this);
}
};
obj.b(); // undefined {}
obj.c(); // 10 { i: 10, b: [Function: b], … } 49
Case-insensitive search
If we wanted to make this case insensitive, we could do:
const index = [Link](
element => [Link]() === 'strawberry');

This is a lot more elegant than the for-loop approach!

for (let i = 0; i < [Link]; i++) {


if (flavors[i].toLowerCase() === 'strawberry') {
break;
}
}
const index = i;
50
[Link]
- Used to create a new array from calling a function for
each element of an existing array.
- Syntax:
[Link](function(currentValue, index, arr), thisValue)
Parameter Description
function() Required. A function to be run for each array element.
currentValue Required. The value of the current element.
index Optional. The index of the current element.
arr Optional. The array of the current element.
thisValue Optional. Default value undefined.
A value passed to the function to be used as its this value.

51
[Link]
E.g., Map an array of objects to an array of strings:

const persons = [
{firstname : "Malcom", lastname: "Reynolds"},
{firstname : "Kaylee", lastname: "Frye"},
{firstname : "Jayne", lastname: "Cobb"}
];

[Link]([Link]((p) => {
return [[Link], [Link]].join(" ");
}));

52
[Link]
- Executes a reducer function on each element of the array and
returns a single output value. Syntax:
[Link](function(total, currentValue, currentIndex, arr), initialValue)
Parameter Description
function() Required. A function to be run for each element in the array.
Reducer function parameters:
total Required. The initialValue, or the previously returned value of the function.
currentValue Required. The value of the current element.
currentIndex Optional. The index of the current element.
arr Optional. The array the current element belongs to.
initialValue Optional. A value to be passed to the function as the initial value.
Note: - Normally, array element 0 is used as initial value, and the iteration starts
from array element 1.
- If an initial value is supplied, this is used, and the iteration starts from
array element 0
53
[Link]
E.g., Find sum of elements in an array:

const numbers = [ 1, 2, 5, 3, 6, 7 ];
const sum = [Link](
(acc, num) => acc + num,
0 // Init value for acc
);

[Link](sum);

54
Currying

55
Currying
Change a function having multiple arguments into a sequence of
functions with a single argument.
Ex: function add(a, b) function curryAdd(a)
{ return a + b; } { return function(b)
{ return a + b; } }

Then, you can use it like this: const add = curryAdd(5);


[Link](add(3)); // Outputs 8
OR
[Link](curryAdd(5)(3))

56
Currying
Recall: [Link] Example
const flavors =
['vanilla', 'chocolate', 'strawberry', 'green tea'];

function isStrawberry(element) {
return element === 'strawberry';
}
const indexOfStrawberry = [Link](isStrawberry);

What if instead of checking specifically for strawberry.


we wanted to create a generic isFlavor checker?
function isFlavor(flavor, element) {
return element === flavor;
}
57
Currying

const flavors =
['vanilla', 'chocolate', 'strawberry', 'green tea'];

function isFlavor(element) {
// ERROR: flavor is undefined!
return element === flavor;
}

const indexOfFlavor = [Link](isFlavor);

The problem is there's no way to pass in the flavor


parameter in the callback for findIndex...
58
Currying

const flavors =
['vanilla', 'chocolate', 'strawberry', 'green tea'];

function createFlavorTest(flavor) {
function isFlavor(element) {
return element === flavor;
}
return isFlavor;
}
const isStrawberry = createFlavorTest('strawberry');
const indexOfFlavor = [Link](isStrawberry);

Solution: Create a function that takes a flavor parameter


and creates a testing function for that parameter
59
Aside: closure

const flavors =
['vanilla', 'chocolate', 'strawberry', 'green tea'];

function createFlavorTest(flavor) {
function isFlavor(element) {
return element === flavor;
}
return isFlavor;
}
const isStrawberry = createFlavorTest('strawberry');
const indexOfFlavor = [Link](isStrawberry);

Aside: Any function that is declared within another function


is called a closure. Closures can refer to variables in the
outer function (flavor in this case) 60
Currying

function isFlavor(flavor, element) {


return element === flavor;
}

This idea is called


function createFlavorTest(flavor) { currying: breaking down
function isFlavor(element) {
a function with multiple
return element === flavor;
} arguments by applying
return isFlavor; one at a time in a
}
sequence of created
[Link](isFlavor);
functions
func(a, b, c) => func( a )( b )( c )
61
Review: Functional JavaScript

Functions in JavaScript are first-class citizens:


- Objects that can be passed as parameters

- Can be created within functions:


• Inner functions are called closures

- Can be created without being saved to a variable


• These are called anonymous functions, or
function literals, or lambdas
- Can be created and returned from functions
• Constructing a new function that references
part of the outer function's parameters is called
currying 62
Promises:
Another conceptual odyssey

63
Promises and .then()

A Promise:
- An object representing the eventually result of an
asynchronous operation
- Has a then() method that lets you attach functions to
execute onSuccess or onError
- Allows you to build chains of asynchronous results

Promises are one way to deal with asynchronous code, without getting stuck in callback hell.
64
Promise’s constructor syntax

● A promise can be created with the constructor syntax


let promise = new Promise(function(resolve, reject)
{ // Code to execute });
● The constructor function takes a function as an argument.
This function is called the executor function
// Executor function passed to the
// Promise constructor as an argument
function(resolve, reject)
{ // Your logic goes here... }
+ Two arguments resolve and reject are the callbacks provided by the
JavaScript language
+ Your logic goes inside the executor function that runs automatically
when a new Promise is created 65
Promise’s constructor syntax

66
Promise’s constructor syntax

● The new Promise() constructor returns a promise object.


● A promise object has the following internal properties:
+ State – This property can have the following values:
 pending: Initially when the executor function starts the execution
 fulfilled: When the promise is resolved.
 rejected: When the promise is rejected.
+ Result – This property can have the following values:
 undefined: Initially when the state value is pending.
 value: When resolve(value) is called.
 error: When reject(error) is called.
Note:
- These internal properties are code-inaccessible but they are inspectable. This means that
we will be able to inspect the state and result property values using the debugger tool
- A promise that is either resolved or rejected is called settled 67
Promise’s constructor syntax
● In a promice, we can attach 3 methods:
.then(): Gets called after a promise resolved.
.catch(): Gets called after a promise rejected.
.finally(): Always gets called, whether the promise resolved
or rejected.

68
Promise’s constructor syntax

69
Promise’s constructor syntax

70
Promise: A consumer function
● A consumer function (that uses an outcome of the promise)
should get notified when the executor function is done with
either resolving (success) or rejecting (error).

let done = true


let promise = new Promise(function(resolve,
reject) {
if (done) {
resolve('I am done'); }
else
{
reject('Still working on something else');}
});
[Link](
(result) => {[Link](result);},
(error) => {[Link](error);});

71
Promise: A consumer function

● You can handle errors in a better way using


the .catch() method

let done = true


let promise = new Promise(function(resolve, reject) {
if (done) {
resolve('I am done');
}
else
{
reject('Still working on something else');
}
});

promise
.then((result) => {[Link](result);})
.catch((error) => {[Link](error);});

72
Promise: A consumer function

● An important point to note:


“A Promise executor should call only one resolve or one reject. Once
one state is changed (pending => fulfilled or pending => rejected),
that's all. Any further calls to resolve or reject will be ignored.”
let promise = new Promise(function(resolve, reject) {
resolve("I am surely going to get resolved!");

reject(new Error('Will this be ignored?')); // ignored


resolve("Ignored?"); // ignored});

73
Promise: Fetch API
Không cần
thiết nếu dùng
npm install node-fetch@2 node v18.x

const fetch = require('node-fetch');

const url = '[Link]

function onSuccess(response) { … }
function onFail(error) { … }
fetch(url).then(onSuccess, onFail);

74
Promise : Fetch API

Q: How does this syntax work?

fetch(url).then(onSuccess, onFail);

75
Promise: Fetch API

Q: How does this syntax work?

fetch(url).then(onSuccess, onFail);

The syntax above is the same as:

const promise = fetch(url);


[Link](onSuccess, onFail);

76
Promise: Fetch API

const promise = fetch(url);


[Link](onSuccess, onFail);

The object fetch returns is of type Promise

A promise is in one of three states:


- pending: initial state, not fulfilled or rejected
- fulfilled: the operation completed successfully
- rejected: the operation failed

You attach handlers to the promise via .then()


77
Promise chaining

.then() returns a promise, so we can call a next .then() on it

78
Promise chaining

.then() returns a promise, so we can call a next .then() on it

new Promise((resolve, reject) => {


setTimeout(() => resolve(1), 1000);
}).then(result => result * 2)
.then(result => result * 2)
.then((result) => {
[Link](result); // 4
});

79
Promise chaining
You can return a promise from a .then() handler method. You will go
for it when you have to initiate an async call based on a response
from a previous async call.

80
Error handling

You can throw an error from the .then() handler. If you have a .catch()
method down the chain, it will handle that error. If we don't handle
the error, an unhandledrejection event takes place.
fetch(url)
.then(onSuccess)
.catch(onFail);

81
.then() .then().catch()
Error handling

82
Error handling

You can rethrow from the .catch() handler to handle the error later. In
this case, the control will go to the next closest .catch() handler.

83
[Link](iterable)

[Link]():
₋ Returns a single Promise that resolves to an array of the
results of the input promises
₋ It rejects immediately upon any of the input promises
rejecting

84
[Link](iterable)

[Link](): wait for all input promises to


complete, regardless of whether or not one rejects

85
async/await

86
Asynchronous fetch()

function onJsonReady(json) {
[Link](json);
}

The usual
function onResponse(response) {
asynchronous return [Link]();
fetch() looks like }
this:
fetch(url)
.then(onResponse)
.then(onJsonReady);

87
Synchronous fetch()?
A hypothetical synchronous fetch() might look like this:

// THIS CODE DOESN'T WORK


const response = fetch(url);
const json = [Link]();
[Link](json);

This is a lot cleaner code-wise!!


However, a synchronous fetch() would freeze the event
loop as the resource was downloading, which would be
terrible for performance

88
async / await

What if we could get the best of both worlds?


- Synchronous-looking code
- That actually ran asynchronously

// THIS CODE DOESN'T WORK


const response = fetch(url);
const json = [Link]();
[Link](json);

89
async / await

What if we could get the best of both worlds?


- Synchronous-looking code
- That actually ran asynchronously

// But this code does work:


async function loadJson(url) {
const response = await fetch(url);
const json = await [Link]();
[Link](json);
}
loadJson('[Link]
90
async / await

What if we could get the best of both worlds?


- Synchronous-looking code
- That actually ran asynchronously

// But this code does work:


async function loadJson(url) {
const response = await fetch(url);
const json = await [Link]();
[Link](json);
} ???
loadJson('[Link]
91
async functions

A function marked async has the following qualities:


- It will behave more or less like a normal function if you
don't put await expression in it

- An await expression is of form:


• await promise

92
async functions

A function marked async has the following qualities:


- If there is an await expression, the execution of the
function will pause until the Promise in the await
expression is resolved
• Note: The event loop is not blocked; it will continue processing other
events as the async function is paused

- Then when the Promise is resolved, the execution of


the function continues
- The await expression evaluates to the resolved value
of the Promise
93
function onJsonReady(json) {
[Link](json);
} The methods in
function onResponse(response) {
return [Link](); purple return
}
fetch(url) Promises
.then(onResponse)
.then(onJsonReady);

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
}
loadJson('[Link] 94
function onJsonReady(json) {
[Link](json);
} The variables in
function onResponse(response) {
return [Link](); blue are the values
}
fetch(url) that the Promises
.then(onResponse)
.then(onJsonReady);
"resolve to"

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
}
loadJson('[Link] 95
async functions

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
}
loadJson('[Link]

96
async functions

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
}
loadJson('[Link]

97
async functions

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
}
loadJson('[Link]

Since we've reached an await statement, two things happen:


1. fetch(url); runs
2. The execution of the loadJson function is paused here until
fetch(url); has completed 98
async functions

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
}
loadJson('[Link]
[Link]('after loadJson');

At the point, the JavaScript engine will return from loadJson()


and it will continue executing where it left off

99
async functions

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
}
loadJson('[Link]
[Link]('after loadJson');

100
async functions

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
}
loadJson('[Link]
[Link]('after loadJson');

101
async functions

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
}
loadJson('[Link]
[Link]('after loadJson');

102
async functions

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
}
loadJson('[Link]
[Link]('after loadJson');

If there are other events and we had a event handler for it,
JavaScript will continue executing those events

103
async functions

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
}
loadJson('[Link]
[Link]('after loadJson');

When the fetch() completes, the JavaScript engine will resume


execution of loadJson()

104
Recall: fetch() resolution

function onResponse(response) {
return [Link]();
}
fetch(url)
.then(onResponse);

Normally when fetch() finishes, it executes the onResponse


callback, whose parameter will be response
In Promise-speak:
- The return value of fetch() is a Promise that resolves to
the response object
105
async functions

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
}
loadJson('[Link]
[Link]('after loadJson');

The value of the await expression is the value that the Promise
resolves to, in this case response

106
async functions

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
}
loadJson('[Link]
[Link]('after loadJson');

107
async functions

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
}
loadJson('[Link]

Since we've reached an await statement, two things happen:


1. [Link](); runs
2. The execution of the loadJson function is paused here until
[Link](); has completed
108
async functions

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
}
loadJson('[Link]

If there are other events and we had a event handler for it,
JavaScript will continue executing those events

109
async functions

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
}
loadJson('[Link]

When the [Link]() completes, the JavaScript engine


will resume execution of loadJson()

110
Recall: json() resolution

function onJsonReady(jsObj) {
Normally when json()
[Link](jsObj);
} finishes, it executes the
function onResponse(response) { onJsonReady callback,
return [Link](); whose parameter will
} be jsObj
fetch(url)
.then(onResponse)
.then(onJsonReady);

In Promise-speak:
- The return value of json() is a Promise that resolves to the
jsObj object 111
async functions

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
}
loadJson('[Link]

The value of the await expression is the value that the Promise
resolves to, in this case json

112
async functions

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
}
loadJson('[Link]

113
async functions

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
}
loadJson('[Link]

114
async functions

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
}
loadJson('[Link]

Note that the JS execution does *not* return back to the call
site, since the JS execution already did that when we saw the
first await expression
115
Returning from async

Q: What happens if we return a value from an async


function?

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
return true;
}
loadJson('[Link]

116
Returning from async
A: async functions must always return a Promise

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
return true; If you return a value that is not a
} Promise (such as true), then the
loadJson('[Link] JavaScript engine will automatically
wrap the value in a Promise that
resolves to the value you returned

117
Returning from async

function loadJsonDone(value) {
[Link]('loadJson complete!');
[Link]('value: ' + value); // value: true
}

async function loadJson(url) {


const response = await fetch(url);
const json = await [Link]();
[Link](json);
return true;
}
loadJson('[Link]
[Link]('after loadJson');
118
Error handling with async/await

async function loadJson(url) {


try {
const response = await fetch(url);
const json = await [Link]();
[Link](json);
} catch (error) {
[Link]([Link]);
} finally {
[Link]('Done');
}
}
loadJson('[Link]

119
Error handling with async/await

const handlePromise = promise => {


return [Link](data => [null, data])
.catch(error => [error, undefined]);
}

async function fetchJson() {


let response = await fetch('[Link]
if (![Link]) {
throw new Error(`Error: ${[Link]}`);
}
return [Link]();
}

let [error, json] = await handlePromise(fetchJson()); 120


More async

- Constructors cannot be marked async


• A constructor returns the object being created while
an async method returns a promise

- But you can pass async functions as parameters to


wherever you can pass a function as a parameter

121
To get the return value from a
function in JavaScript
It depends on the function in question (check its docs)
// funct is synchronous
const retValue = funct();

// funct is asynchronous, callback version


funct(function(retValue) { … });

// funct is asynchronous, Promise version


funct().then(function(retValue) { … });

(async function caller() {


const retValue = await funct();
})(); 122
123
124
125
126
127
128
JSON

129
JavaScript Object Notation

JSON: stands for JavaScript Object Notation


- Created by Douglas Crockford
- Defines a way of serializing JavaScript objects
• to serialize: to turn an object into a string that can
be deserialized
• to deserialize: to turn a serialized string into an
object
- Built on two structures: a collection of name/value
pairs and an ordered list of values

130
JavaScript Object Notation

JSON: stands for JavaScript Object Notation


- A value can be a string in double quotes, or a number,
or true or false or null, or an object or an array. These
structures can be nested
- Don’t support comments

- [Link](object) returns a string


representing object serialized in JSON format
- [Link](jsonString) returns a JS object from the
jsonString serialized in JSON format

131
[Link]()

We can use the [Link]() function to seralize a


JavaScript object:

const bear = {
name: 'Ice Bear',
hobbies: ['knitting', 'cooking', 'dancing']
};

const serializedBear = [Link](bear);


[Link](serializedBear);

132
[Link]()

We can use the [Link]() function to deseralize a JavaScript


object:

const bearString = '{


"name":"Ice Bear",
"hobbies":["knitting","cooking","dancing"]
}';

const bear = [Link](bearString);


[Link](bear);

133
Why JSON?

JSON is a useful format for storing data that we can load


into a JavaScript API

Let's say we had a list of Songs and Titles


- If we stored it as a text file, we would have to know
how we are separating song name vs title, etc
- If we stored it as a JSON file, we can just deserialize the
object

134
JSON

135
Some other features/syntax

136
Destructuring arrays/objects
When you are destructuring an object, the
name of the variables should match the
name of the properties of the object
otherwise, the destructuring will not work
let [a, b] = [ 1, 2, 3, 4 ]; and the value of the variable would
be undefined
[Link](a); // 1
[Link](b); // 2

let details = { firstName: 'Code', lastName:


'Burst', age: 22 };
let { firstName, age } = details;

137
Alias variables

const { identifier: alias } = expression;

const hero = {
name: 'Batman'
};
// Object destructuring:
const { name: heroName } = hero;
[Link](heroName); // 'Batman'

138
Dynamic property names

const x = 'name';
const a = { [x]: 'Batman' }
[Link]([Link]); // 'Batman'
[Link](a[x]); // 'Batman'

const property = 'name';


const hero = {
name: 'Batman'
};
const { [property]: heroName } = hero;
[Link](heroName); // 'Batman' 139
Spread operator (…)

Operator (...) allows us to quickly copy all or


part of an existing array or object into another
array or object
let numberStore = [0, 1, 2];
let newNumber = 12;
numberStore = [...numberStore, newNumber];
=> numberStore = [0, 1, 2, 12]

let arr = [1, 2, 3];


let arr2 = [...arr];
=> arr2 = [1, 2, 3]

140
Spread operator (…)
Operator (...) allows us to quickly copy all or
part of an existing array or object into another
array or object
let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
arr1 = [...arr1, ...arr2];
 arr1 = [0, 1, 2, 3, 4, 5]

Assign the first and second items from numbers to


variables and put the rest in an array
const numbers = [1, 2, 3, 4, 5, 6];
const [one, two, ...rest] = numbers;
 [one, two, ...rest] = [0, 1, 2, 3, 4, 5]
 [one, two, ...rest] = [1, 2, 3, 4, 5, 6]
141
Spread operator (…)

let obj1 = { foo: 'bar', x: 42 };


let obj2 = { foo: 'baz', y: 13 };

let clonedObj = { ...obj1 };


// Object { foo: "bar", x: 42 }

let mergedObj = { ...obj1, ...obj2 };


// Object { foo: "baz", x: 42, y: 13 }

Notice the properties that did not match were combined, but the property that did match,
color, was overwritten by the last object that was passed, mergedObj. The resulting foo is
now ‘baz’.
142
Rest operator (…)
const numbers = [1, 2, 3];
const [ first, ...restOfTheNumbers ] = numbers;
=> [ first, ...restOfTheNumbers ] = [1,2,3]
const [firstletter, ...restOfTheLetters ] = 'webdev';
=> [firstletter, ...restOfTheLetters ] = [ 'w', 'e',
'b', 'd', 'e', 'v' ]
const details = { firstName: 'Code',lastName:
'Burst',age: 22};

const { age, ...restOfTheDetails } = details;


=> { age, ...restOfTheDetails } = { age: 22,
firstName: 'Code', lastName: 'Burst' }
143
Module Systems

144
The need for modules

 Having a way to split the codebase into multiple files


 Allowing code resuse across different projects
 Encapsulation/Information hiding
 Managing dependencies

The distinction between a module and a module system


 A module: an actual unit of software (i.e., a .js file)
 A module system: syntax and tooling that allows us to
define and use modules

145
The need for modules

JavaScript had been lacking this feature for a long time

 Splitting the codebase into multiple files and importing


them by using different <script> tags was good enough

 Immediately Invoked Function Expression (IIFE) pattern is


used to create a private scope, exporting only public parts

146
Immediately Invoked Function
Expression (IIFE)

const myModule = (() => {


const privateFoo = () => {}
const privateBar = []
const exported = {
publicFoo: () => {}
publicBar: () => {}
}
return exported;
})();

[Link](); 147
CommonJS modules

 Each file is treated as a separate module

 The [Link] is a special object which is included in


every JavaScript file in the [Link] application by default

 Whatever you assign to [Link] can be exposed to


other modules/files

• require(path/to/file)
• require(path/to/folder): [Link] file in the folder
will be used (for nodejs)
148
CommonJS modules

// [Link]
const { PI } = Math;
[Link] = (r) => PI * r ** 2;
[Link] = (r) => 2 * PI * r;

// [Link]
const circle = require('./[Link]');
[Link](`The area of a circle of radius 4 is
${[Link](4)}`);

149
CommonJS modules

// [Link]
class Square {
constructor(width) { [Link] = width; }
area() { return [Link] ** 2; }
};
[Link] = Square;

// [Link]
const Square = require('./[Link]');
const mySquare = new Square(2);
[Link](`The area of mySquare is
${[Link]()}`); 150
ECMAScript modules

 Official standard format to package JS code for reuse

 Use import/export instead of [Link]/require

 Full support from [Link] 13.2.0 (also supported in most


browsers)

 For [Link], must use .mjs file extension, or put "type":


"module" in the nearest [Link] file 151
ECMAScript modules
// [Link]
const { PI } = Math;
export const area = (r) => PI *Named
r ** export
2;
let baseCircle
export const circumference = (r) => 2 * PI * r;
export default baseCircle = {
r: 10, Default export
printInfo() {
[Link](this.r, area(this.r),
circumference(this.r));
}
Note: Only one default
}; export per module
152
ECMAScript modules

// [Link]
// import named exports within curly braces with
// the same name
import circle, { area, circumference as c }
from './[Link]';

// a default export can be imported with any name


import stdCircle from './[Link]';

// or import everything
import * as circle from './[Link]';
// [Link] to access the default export (if any)
153
Module bundling
 The process of stitching together a group of modules
(and their dependencies) into a single file (or group of
files) in the correct order*
• Usually involve some optimizations (i.e., removing
spaces to reduce file size)

 Write code using a certain module system/syntax (i.e.,


es6) and convert to different module system/syntax
(i.e., cjs, iife)

 Several tools available: webpack, rollup, parcel,…

154
*[Link]

You might also like