let js = 'amazing'; if (js === 'amazing') alert('Javascript is FUN!'); js = 'boring'; if (js === 'amazing') alert('Javascript is FUN!');
javascript is a high-level object-oriented, multi-paradigm programming language
programming language: instruct computer to do things high level: we dont have to worry about complex stuff like memory management object oriented: based on objects, for storing most kinds of data multi paradigm: we can use different styles of programming
dynamic effects and web applications in the browser -> react agular vue
web applications on web servers -> nodejs
native mobile applications -> native react, ionic
native desktop applications -> electorn
ES6/ES2015
1 2
40 + 8 + 23 - 10; console.log(40 + 8 + 23 - 10);
value and variables
1 2 3 4 5 6 7
console.log('Jonas'); console.log(23);
let firstName = 'Matilda'; console.log(firstName); console.log(firstName); console.log(firstName);
camlcase let first = 'Jonas'; let firstNamePerson;
error number first let 2ads = 2;
letter number8 undersocre_ dollarsign$
no key word
constants PI
class name Person
name descriptive let myFirstJob = 'Programmer'; let myCurrentJob = 'Teacher'; not let job1 = 'Programmer'; let job2 = 'Teacher';
data types
dymatic type
object or primitive
primitive
number floating point used for dicimals and integers
string sequence of characters
boolean true or false
undifined value taken by a variable that is not yet defined(‘empty value’) let children;
const age = 15; // const age = 19; // const isOldEnough = age >= 18;
// if (isOldEnough) { // console.log('Sarah can start driving licese!'); // }
if (age >= 18) { console.log('Sarah can start driving licese!'); } else { const yearsLeft = 18 - age; //Sarah is too young. Wait another 3 years :) console.log(`Sarah is too young. Wait another ${yearsLeft} years :)`); }
// const birthYear = 1991; const birthYear = 2012; let century; if (birthYear <= 2000) { // let century = 20; century = 20; } else { century = 21; }
// Uncaught ReferenceError: century is not defined // console.log(century);
// const money = 0; // you should get a job const money = 100; // dont spent it all if (money) { console.log('dont spent it all'); } else { console.log('you should get a job'); }
let height; // height is undefined // let height = 0; // height is undefined // let height = 100; // height is defined if (height) { console.log('height is defined'); } else { console.log('height is undefined'); }
// no type coercion if (age === 18) console.log('You just became an adult!');
// true if ('18' == 18) console.log('You just became an adult!'); // if (Number('18') == 18) console.log('You just became an adult!');
// false if ('18' === 18) console.log('You just became an adult!');
// input: 23 let favourite = prompt("What's your favorite number?"); console.log(favourite); // '21' console.log(typeof favourite); // 'string'
if (favourite == 23) { console.log('23 is an amazing number!'); }
if (Number(favourite) === 23) { console.log('23 is an amazing number!'); }
favourite = Number(favourite); if (favourite === 23) { console.log('23 is an amazing number!'); } elseif (favourite === 7) { console.log('7 is an amazing number!'); } else { console.log('number is not 7 or 23!'); }
// parameters functionfruitProcessor(apples, oranges) { // console.log(apples, oranges); const juice = `Juice with ${apples} apples and ${oranges} oranges.`; return juice; }
//arguments const appleJuice = fruitProcessor(5, 0); // Juice with 5 apples and 0 oranges. console.log(appleJuice); // 5 3 // Juice with 5 apples and 3 oranges. console.log(fruitProcessor(5, 3));
// bracket can be any experssion console.log(jonas["lastName"]); // "Schmed" // bracket can be any experssion const nameKey = 'Name'; console.log(jonas[`first${nameKey}`]); // Jonas console.log(jonas['last' + nameKey]); // "Schmed"
//input 'job' const interestedIn = 'job'; // const interestedIn = prompt('What do you want to know about Jonas? Choose from firstName, lastName, age, job, and friends'); console.log(interestedIn); console.log(jonas[interestedIn]); // console.log(jonas.interestedIn); // jonas.interestedIn ===> undefinded
if (jonas[interestedIn]) { console.log(jonas[interestedIn]); } else { console.log('wrong request'); }
//Jonas has 3 friends, and his best friend is called Michael console.log(`${jonas.firstName} has ${jonas.friends.length} friends, and his best friend is called ${jonas.friends[0]}`);
// selfIntro: function () { // return `${this.firstName} is a ${2037 - this.birthYear}-year old ${this.job}, and he has ${this.hasDriverLicense ? 'a' : 'no'} driver's license`; // } calcAge: function () { this.age = 2037 - this.birthYear; returnthis.age; }, selfIntro: function () { return`${this.firstName} is a ${this.calcAge()}-year old ${this.job}, and he has ${this.hasDriverLicense ? 'a' : 'no'} driver's license.`; }
}; // Jonas is a 46-year old teacher, and he has a driver's license console.log(jonas3.selfIntro());
for (let i = 0; i < years.length; i++) { ages.push(2037 - years[i]); } //[46, 30, 68, 17] console.log(ages);
// continue and break // continue: skip this iteration // break: finish the whole loop
console.log('-------all items-------------'); for (let i = 0; i < jonas.length; i++) { console.log(jonas[i], typeof jonas[i]); }
console.log('-------only strings-------------'); for (let i = 0; i < jonas.length; i++) { if (typeof jonas[i] !== 'string') { continue; } console.log(jonas[i], typeof jonas[i]); }
console.log('-------break with number-------------'); for (let i = 0; i < jonas.length; i++) { if (typeof jonas[i] === 'number') { break; } console.log(jonas[i], typeof jonas[i]); }
let rep = 1; while (rep <= 5) { console.log(`lifting weights repetition ${rep}`);
rep++; }
let dice = Math.trunc(Math.random() * 6) + 1; // console.log(dice);
while (dice !== 6) {
console.log(`You rolled a ${dice}`); dice = Math.trunc(Math.random() * 6) + 1; if (dice === 6) { console.log('dice is 6, loop is about to end...'); } }
developer skills
DOM AND EVENT – guess my number
console.log(document.querySelector('.message')); // element p.message
javascript is a high level, prototype-based object-oriented, multi-paradigm, interpreted or just-in-time compied, dynamic, single-threaded, garbage-collected programming language with first-class functions and a non-blocking event loop concurrency model.
high level manage computer resources automatically garbage-collected
interpreted or just in time compiled javascirpted engine
multi-paradigm paradigm: an approach and mindset of structuring code, which will direct your coding style and technique.
procedural
objected oriented
functional
prototype-based object oriented
first-class functions functions are simply treated as variables. we can pass them into other functions, return them from functions.
dynamic type no data type when variable definitons. data type of variable is automatically changed
single-threaded non-blocking event loop
concurrency model: the javascript engine handles multiple tasks happpening at the same time. event loop: takes long running tasks, executes them in the background, and put them back in the main thread once they are finished.
javascript engine and runtime
program that executes javascript code.
v8 engine chrome, nodejs
call stack heap
compilation vs interpretation compilation: entire code is coverted into machine code at once, and written to a binary file that can be executed by a computer. interpretation: interpreter runs through the source code and executes it line by line.
just-in-time comilation entire code is converted into machine code at once, then executed immediately.
parse into AST: abstract signtax tree
re-compilate optimization
js runtime in the browser
nodejs runtime
execution contexts and the call stack
exeution context environment in which a piece of javascript is executed. stores all the necessary information for some code to be executed.
one global execution context(ec) default context, created from code that is not inside any function(top level)
function execution context(ec) for each function call, a new execution context is created.
varialbe environment
let, const and var declarations
Functions
arguments object
scope chain: consists of references to varialbes that are lacated outside of the function
this keyword
!!! arrow functin dont have arguents object, this keyword they used the arguemnt object and this keyword from the closest function pareant.
call stack: place where execution contexts get stacked on top of each other, to keep track of where we are in the execution.
scope and scope chain
scoping: how programs’s variabes are organized and accessed. “where do variables live?” or “where can we access a certain vairalbe, and where not?”
lexical scoping: scoping is controlled by placement of functions and blocks in the code; example like: a function write inside another function can have access to variable of the parent function
scope: space or environment in which a certain variable is declared(variable environment in case of functions scope). there is global scope, function scope, and block scope;
scope of a variable: region of our code where a certain variable can be accessed
3 types of scope
global scope
1 2 3
const me = 'Jonas'; const job = 'teacher'; const year = 1989;
outside of any function or block variable declared in global scope are accessible everywhere
function scope
1 2 3 4 5 6 7
functioncalcAge(birthYear) { const now = 2037; const age = now - birthYear; return age; }
console.log(now) // ReferenceError
variables are accessible only inside function, Not outside also called local scope
block scope (ES6)
1 2 3 4 5 6 7
// example: if block, for loop block, etc if(year >= 1981 && year <= 1986) { const millenial = true; const food = 'Avocado toast'; }
console.log(millenial) // ReferenceError
variable are accessible only inside block(block scoped) however, this only applies to let and const variables! functions are also block scoped(only in strict mode)
functioncalcAge(birthYear) { const age = 2037 - birthYear; console.log(firstName); // no errors // console.log(lastName); // ReferenceError
functionprintAge() { let output = `${firstName} You are ${age}, born in ${birthYear}`; console.log(output);
if (birthYear >= 1981 && birthYear <= 1996) { var millenial = true;
// // scope chain shadow: create new variable with the same name as outer scope's variable // const firstName = 'Steven' // const str1 = `oh, you are a millenial, ${firstName}`; // // oh, you are a millenial, Steven // console.log(str1);
// // set the value again, reassigning outer scope's varialbe // output = "New output!";
const str = `oh, you are a millenial, ${firstName}`; //oh, you are a millenial, Jonas console.log(str); // no error
functionadd(a, b) { return a + b; } } // // set the value again, reassigning outer scope's varialbe // output = "New output!"; // // "New output!" // console.log(output);
// Uncaught ReferenceError: str is not defined // console.log(str);
// var vairale is function scoped console.log(millenial); // no error "true"
// in strict mode // function defined in block is block scoped //script.js:80 Uncaught ReferenceError: add is not defined // add(2, 3); // error } // Jonas You are 46, born in 1991 printAge(); // no error return age; }
const firstName = 'Jonas'; calcAge(1991); // Uncaught ReferenceError: age is not defined // console.log(age); //Uncaught ReferenceError: printAge is not defined // printAge();
variable environment: hoisting
hoisting:makes some types of variable acessible/usable in the code before they are actually declared. “ variables lifted to the top of their scope”. before execution, code is scanned for variable declarations, and for each variable, a new property is created in the variable environment object.
temporal dead zone
1 2 3 4 5 6 7 8 9 10 11 12 13 14
const myName = "Jonas";
if (myName === 'Jonas') { // Uncaught ReferenceError: Cannot access 'job' before initialization // console.log(`Jonas is a ${job}`);
this keyword/variable: special variable that is created for every execution context(every funtion). Takes the value of(point to) the “owner” of the function in which the this keyword is used.
this is NOT static. it depends on how the function is called, and its valued is only assigned when the function is acturally called.
///////////////// primitive type let lastName = 'Williams'; let oldLastName = lastName; lastName = "Davis"; console.log(lastName); // Davis console.log(oldLastName); // Williams
// 2 2 '22:30' 'via del sole, 21' // Order received! Garlic Bread and Risotto will be delivered to via del sole, 21 at 22:30 restaurant.orderDelivery1({ time: '22:30', address: 'via del sole, 21', mainIndex: 2, starterIndex: 2, })
// 2 2 '22:30' 'via del sole, 21' // Order received! Garlic Bread and Risotto will be delivered to via del sole, 21 at 22:30 restaurant.orderDelivery1({ time: '22:30', address: 'via del sole, 21', mainIndex: 2, starterIndex: 2, })
// 1 0 '20:00' 'via del ssdole, 21' // Order received! Bruschetta and Pizza will be delivered to via del ssdole, 21 at 20:00 restaurant.orderDelivery1({ address: 'via del ssdole, 21', starterIndex: 1, })
// 2 2 '22:30' 'via del sole, 21' // Order received! Garlic Bread and Risotto will be delivered to via del sole, 21 at 22:30 restaurant.orderDelivery1({ time: '22:30', address: 'via del sole, 21', mainIndex: 2, starterIndex: 2, })
// 1 0 '20:00' 'via del ssdole, 21' // Order received! Bruschetta and Pizza will be delivered to via del ssdole, 21 at 20:00 restaurant.orderDelivery1({ address: 'via del ssdole, 21', starterIndex: 1, })
const add = function (...numbers) { console.log(numbers); let sum = 0; for (let i = 0; i < numbers.length; i++) { sum += numbers[i]; } console.log(sum); }
const menu = [...restaurant.starterMenu, ...restaurant.mainMenu]; console.log(menu);
// Focaccia // Bruschetta // Garlic Bread // Caprese Salad // Pizza // Pasta // Risotto for (const item of menu) { console.log(item); } // can use break and continue
// Array Iterator {} console.log(menu.entries());
for (const item of menu.entries()) { // [0, 'Focaccia'] console.log(item); // '1: Focaccia' console.log(`${item[0] + 1}: ${item[1]}`);
// if (restaurant.openingHours.mon) console.log(restaurant.openingHours.mon.open); console.log(restaurant.openingHours.mon?.open);
// if (restaurant.openingHours && restaurant.openingHours.mon) console.log(restaurant.openingHours.mon.open); console.log(restaurant.openingHours?.mon?.open);
const days = ['mon', 'tue', 'wen', 'thu', 'fri', 'sat', 'sun'];
// On mon, we open at closed // On tue, we open at closed // On wen, we open at closed // On thu, we open at 12 // On fri, we open at 11 // On sat, we open at 0 // On sun, we open at closed for (const day of days) { // console.log(day); const open = (restaurant.openingHours[day]?.open) ?? 'closed'; console.log(`On ${day}, we open at ${open}`); }
///// on methods // ['Focaccia', 'Pasta'] console.log(restaurant.order?.(0, 1) ?? 'Method does not exist'); // Method does not exist console.log(restaurant.orderRisotto?.(0, 1) ?? 'Method does not exist');
let openStr = `We are open on ${Object.keys(openingHours).length} days: `; // thu // fri // day-6 // sat for (const day ofObject.keys(openingHours)) { // console.log(day); openStr += `${day},`; }
// We are open on 4 days: thu,fri,day-6,sat, console.log(openStr);
const question = newMap([ ['question', 'Waht is the best programmong language in the world?'], [1, 'C'], [2, 'java'], [3, 'javascritp'], ['correct', 3], [true, 'you are Correct!'], [false, 'Try again'], ]); // Map(7) {'question' => 'Waht is the best programmong language in the world?', 1 => 'C', 2 => 'java', 3 => 'javascritp', 'correct' => 3, …} console.log(question);
// you are Correct! console.log(question.get(answer === question.get('correct')));
////////convert map to an arrary
// [ // ['question', 'Waht is the best programmong language in the world?'], // [1, 'C'], // [2, 'java'], // [3, 'javascritp'], // ['correct', 3], // [true, 'you are Correct!'], // [false, 'Try again'], // ] console.log('...question', [...question]); // MapIterator {'question', 1, 2, 3, 'correct', …} console.log(question.keys()); // MapIterator {'Waht is the best programmong language in the world?', 'C', 'java', 'javascritp', 3, …} console.log(question.values()); // MapIterator {'question' => 'Waht is the best programmong language in the world?', 1 => 'C', 2 => 'java', 3 => 'javascritp', 'correct' => 3, …} console.log(question.entries());
which data structure to use
sources of data
from the program iteself: data written directly in source code (e.g. status messages)
from the ui: data input from the user or data written in DOM(e.g. tasks in todo app)
From external sources: data fetched for example from web api(e.g. rcipe objects)
simple list key/value pairs: key allow us to describe values
array <> sets array:
use when you need ordered list of values(might contain duplicates)
use when you need to manipulate data
sets
use when you need to work with unique values
use when high-performance is really important
use to remove duplicates form arrays
objects
more ‘traditonal’ key/value store (‘abused’ object)
// first occurance console.log(airline.indexOf('r')); // 6 console.log(airline.indexOf('Portugal')); // 8 console.log(airline.indexOf('portugal')); // -1 // last occurance console.log(airline.lastIndexOf('r')); // 10
console.log(airline.slice(4)); // Air Portugal console.log(airline.slice(4, 7)); // 'Air' console.log(airline); // 'TAP Air Portugal'
console.log(airline.slice(0, airline.indexOf(' '))); // 'TAP' console.log(airline.slice(airline.lastIndexOf(' ') + 1)); // 'Portugal' console.log(airline.slice(-2)); // al console.log(airline.slice(1, -1)); // AP Air Portuga
// B AND E are middle seats const checkMiddleSeat = function (seat) { const s = seat.slice(-1); if (s === 'B' || s === 'E') { console.log('you got the middle seat'); } else { console.log('YOu got lucky'); } } // you got the middle seat checkMiddleSeat('11B') // YOu got lucky checkMiddleSeat('23C') // you got the middle seat checkMiddleSeat('3E')
const announcement = 'All passengers come to barding door 23, Bording door 23!' // just the first occurance // All passengers come to barding gate 23, Bording door 23! console.log(announcement.replace('door', 'gate'));
// regex global flag // All passengers come to barding gate 23, Bording gate 23! console.log(announcement.replace(/door/g, 'gate'));
if (plane.startsWith('Airbus') && plane.endsWith('neo')) { console.log('Part of the new airbus family'); }
/// exercise
const checkBaggage = function (items) { const baggage = items.toLowerCase(); if (baggage.includes('knife') || baggage.includes('gun')) { console.log('You are not allowed on board'); } else { console.log('Welcome aboard'); } } // You are not allowed on board checkBaggage('I have a laptop, some Food and pocket Knife'); // Welcome aboard checkBaggage('Sock and camera'); // You are not allowed on board checkBaggage('Got some snacks and a gun for protection');
const message2 = 'Bad weather... All Departures Delayed...'; // Bad weather... All Departures Delayed...Bad weather... All Departures Delayed...Bad weather... All Departures Delayed... console.log(message2.repeat(3));
const planeInline = function (n) { console.log(`There are ${n} plane in line ${'✈️'.repeat(n)}`); } // There are 5 plane in line ✈️✈️✈️✈️✈️ planeInline(5); // There are 3 plane in line ✈️✈️✈️ planeInline(3); // There are 12 plane in line ✈️✈️✈️✈️✈️✈️✈️✈️✈️✈️✈️✈️ planeInline(12);
// ES 6 // the express can contain the other param before the param const createBooking = function (flightNum, numPassengers = 1 + 0, price = 199 * numPassengers) {
constadd = (a, b) => a + b; const counter = { value: 23, inc: function () { this.value++; } }
// pass functions as arguments to other functions // addEventListenner is higher order function // greet is the callback function constgreet = () => console.log('Hey Jonas'); btnClose.addEventListenner('click', greet);
// return functions form functions // count is the higher order function // // function(){ counter++; } is the returned function functioncount() { let counter = 0; returnfunction () { counter++; } }
// call methods on functions counter.inc.bind(someOtherObject);
high order functions
a function that receives anthoer function as an argument a function that returns a new function or both
// Original string: JavaScript is the best programming language! // Transformed string: JAVASCRIPT is the best programming language! // Trnasformed by: upperFirstWord transformer('JavaScript is the best programming language!', upperFirstWord);
// Original string: JavaScript is the best programming language! // Transformed string: javascriptisthebestprogramminglanguage! // Trnasformed by: oneWord transformer('JavaScript is the best programming language!', oneWord);
// in strict mode // regular functions call "this" is undefined // Uncaught TypeError: Cannot read properties of undefined // book(23, 'Sarah Williams');
// Sarah Williams booked a seat on Eurowings flight EW23 book.call(eurowings, 23, 'Sarah Williams'); // Mary cooper booked a seat on Lufthansa flight LH239 book.call(lufthansa, 239, 'Mary cooper');
// Mary cooper booked a seat on Swiss Air Lines flight LX556 book.call(swiss, 556, 'Mary cooper');
// Apply method const flightData = [583, 'George Cooper']; // George Cooper booked a seat on Swiss Air Lines flight LX583 book.apply(swiss, flightData); book.call(swiss, ...flightData);
const book = lufthansa.book; const bookEW = book.bind(eurowings);
// Steven Williams booked a seat on Eurowings flight EW23 bookEW(23, 'Steven Williams');
/////// partial application const bookEW23 = book.bind(eurowings, 23); // John Smith booked a seat on Eurowings flight EW23 bookEW23('John Smith'); // Martha Cooper booked a seat on Eurowings flight EW23 bookEW23('Martha Cooper');
// button element // NaN document.querySelector('.buy').addEventListener('click', lufthansa.buyPlane) // document.querySelector('.buy').addEventListener('click', lufthansa.buyPlane.bind(lufthansa));
/////// partial application
const addTax = function (rate, value) { return value + value * rate; } // 220 console.log(addTax(0.1, 200));
// addVAT = function (value) { // return value + value * 0.23; // } // created a new function const addVAT = addTax.bind(null, 0.23);
const runOnce = function () { console.log('this will never run again'); }
runOnce(); runOnce();
// Uncaught SyntaxError: Function statements require a function name // function() { // console.log('this will never run again'); // }
(function () { console.log('this will never run again'); // const isPrivate = 23; })();
(() =>console.log('this will also never run again'))();
// function scope
// Uncaught ReferenceError: isPrivate is not defined // console.log(isPrivate);
{ const isPrivate = 23; var notPrivate = 46; }
// Uncaught ReferenceError: isPrivate is not defined // console.log(isPrivate); // 46 console.log(notPrivate);
closures
make functions remenber all the variables where it is birthed place.
a function has access to the variable environment(VE) of the execution context in which it was created. even if it was gone.
closure: VE attached to the function, exactly as it was at the time and place the function was created
closure is priority over scope chain
less formal
a closure is the closed-over variable environment of the execution context in which a function was created, even after that execution context is gone;
a closure give a function aceess to all the variables of its parent function, even after that parent function has returned. The function keeps a reference to its outer scope, which preserves the scope chain throughout time.
a closeure makes sure that a function doesnt lose connection to variable that existed at the function’s birth place
a clsure is like a backpack that a function carries around wherever it goes. This backpack has all the variable that were present in the environment where the function was created.
we can not directly access a closure-over variables explicitly
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
const secureBooking = function () { let passengerCount = 0;
const g = function () { const a = 23; f = function () { console.log(a * 2); } }
const h = function () { const b = 777; f = function () { console.log(b * 2); } }
g(); // 46 f();
console.dir(f)
// re-assigning f function h(); // 1554 f();
console.dir(f)
///// example 2
const boardPassengers = function (n, wait) { const perGoup = n / 3;
// 1s setTimeout(function () { console.log(`we are now boarding all ${n} passengers`); console.log(`There are 3 groups, each with ${perGoup} passengers`); }, wait * 1000);
console.log(`will start boading in ${wait} seconds`); };
// 'will start boading in 3 seconds' //////////////// 3s late // 'we are now boarding all 180 passengers' // 'There are 3 groups, each with 60 passengers'
// closure have high priority const perGoup = 1000;
// Returns a copy of a section of an array. For both start and end, a negative index can be used to indicate an offset from the end of the array. For example, -2 refers to the second to last element of the array. // (3) ['c', 'd', 'e'] console.log(arr.slice(2)); // (2) ['c', 'd'] console.log(arr.slice(2, 4)); // (2) ['c', 'd'] console.log(arr.slice(-3, -1)); // (2) ['b', 'c'] console.log(arr.slice(1, -2)); // (2) ['d', 'e'] console.log(arr.slice(-2)); // copy // (5) ['a', 'b', 'c', 'd', 'e'] console.log(arr.slice()); console.log([...arr]);
////////////// splice
// Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
// @param start — The zero-based location in the array from which to start removing elements.
// @param deleteCount — The number of elements to remove.
// @returns — An array containing the elements that were deleted. // (3) ['c', 'd', 'e'] // console.log(arr.splice(2));
arr.splice(-1);
// ['a', 'b', 'c', 'd'] console.log(arr);
/////////// reverse // Reverses the elements in an array in place. This method mutates the array and returns a reference to the same array.
// map(callbackfn: (value: number, index: number, array: number[]) => any, thisArg?: any): any[] // A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array. // Calls a defined callback function on each element of an array, and returns an array that contains the results.
// filter(predicate: (value: number, index: number, array: number[]) => value is number, thisArg?: any): number[] // A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array. // Returns the elements of an array that meet the condition specified in a callback function. const filteredArr = arr.filter(function (value) { return value > 2; });
// (3) [3, 4, 3] console.log(filteredArr);
// reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number // A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array. // Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. const reducedResult = arr.reduce(function (acc, current) { return acc + current; });
// accumulator // (method) Array<number>.reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number (+2 overloads) // @param initialValue — If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. // const balance = movements.reduce(function (acc, cur, i, arr) { // Iteration 0: 0 // Iteration 1: 200 // Iteration 2: 650 // Iteration 3: 250 // Iteration 4: 3250 // Iteration 5: 2600 // Iteration 6: 2470 // Iteration 7: 2540 console.log(`Iteration ${i}: ${acc}`); return acc + cur; }, 0); // 3840 console.log(balance);
let balance2 = 0; for (const mov of movements) { balance2 += mov; } console.log(balance2);
// (method) Array<number>.find(predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number | undefined (+1 overload) // Returns the value of the first element in the array where predicate is true, and undefined otherwise. // @param predicate //find calls predicate once for each element of the array, in ascending order, until it finds one where predicate returns true. If such an element is found, find immediately returns that element value. Otherwise, find returns undefined. const firstWithdrawal = movements.find(mov => mov < 0); // -400 console.log(firstWithdrawal);
// for of let accountFor = {}; for (const acc of accounts) { if (acc.owner === 'Jessica Davis') { accountFor = acc; } }
console.log(accountFor);
bankist project login page
1 2 3 4 5 6 7 8
const btnLogin = document.querySelector('.login__btn'); btnLogin.addEventListener('click', function (e) { // prevent form form submitting e.preventDefault(); });
const arr = [[1, 2, 3], [4, 5, 6], 7, 8]; // (8) [1, 2, 3, 4, 5, 6, 7, 8] // Returns a new array with all sub-array elements concatenated into it recursively up to the specified depth. // @param depth — The maximum recursion depth console.log(arr.flat());
// (method) Array<string>.sort(compareFn?: ((a: string, b: string) => number) | undefined): string[] // Sorts an array in place. This method mutates the array and returns a reference to the same array.
// @param compareFn // Function used to determine the order of the elements. It is expected to return a negative value if the first argument is less than the second argument, zero if they're equal, and a positive value otherwise. If omitted, the elements are sorted in ascending, ASCII character order. // [11,2,22,1].sort((a, b) => a - b) // (4) ['Adam', 'Jonas', 'Martha', 'Zach'] console.log(owners.sort()); // (4) ['Adam', 'Jonas', 'Martha', 'Zach'] console.log(owners);
// return < 0 , a, b // return > 0 , b, a // (8) [-650, -400, -130, 70, 200, 450, 1300, 3000] console.log(movements.sort((a, b) => { if (a > b) return1; if (b > a) return -1; }));
// (8) [3000, 1300, 450, 200, 70, -130, -400, -650] console.log(movements.sort((a, b) => { if (a > b) return -1; if (b > a) return1; }));
// (8) [-650, -400, -130, 70, 200, 450, 1300, 3000] console.log(movements.sort((a, b) => a - b));
// Changes all array elements from start to end index to a static value and returns the modified array // @param value — value to fill array section with // @param start // index to start filling the array at. If start is negative, it is treated as length+start where length is the length of the array. // @param end // index to stop filling the array at. If end is negative, it is treated as length+end. x.fill(1); // (7) [1, 1, 1, 1, 1, 1, 1] console.log(x);
// all floating 64 console.log(23 === 23.0); // 23 // binary base 2 console.log(0.1 + 0.2); // 0.30000000000000004
// convert string to number console.log(Number('23')); console.log(+'23');
///////// parsing
//(method) NumberConstructor.parseInt(string: string, radix?: number | undefined): number // Converts A string to an integer. // @param string — A string to convert into a number. // @param radix // A value between 2 and 36 that specifies the base of the number in string. If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal. All other strings are considered decimal. console.log(Number.parseInt('30px')); // 30 console.log(Number.parseFloat(' 2.5rem ')); // 2.5
// Only finite values of the type number, result in true. // check if value is number console.log(Number.isFinite(23)); // true console.log(Number.isFinite(23 / 0)); // false console.log(Number.isFinite(+'20x')); // false
// Returns the square root of a number. console.log(Math.sqrt(25)); // console.log(25 ** (1 / 2));
// Returns the larger of a set of supplied numeric expressions. console.log(Math.max(5, '454', 12, 35, 65));
console.log(Math.min(5, '454', 12, 35, 65));
console.log(Math.PI * 10 ** 2);
// random Returns a pseudorandom number between 0 and 1. // trunc Returns the integral part of the a numeric expression, x, removing any fractional digits. If x is already an integer, the result is x. console.log(Math.trunc(Math.random() * 6) + 1);
// Returns a supplied numeric expression rounded to the nearest integer. console.log(Math.round(23.3)); // 23 console.log(Math.round(23.9)); // 24
// Returns the smallest integer greater than or equal to its numeric argument. console.log(Math.ceil(23.3)); // 24 console.log(Math.ceil(23.9)); // 24 console.log(Math.ceil(23)); // 23 // Returns the greatest integer less than or equal to its numeric argument. console.log(Math.floor(23.3)); // 23 console.log(Math.floor(23.9)); // 23 console.log(Math.floor(23)); // 23
console.log(Math.floor(-23.2)); // -24
// when positive value floor === trunc console.log(Math.trunc(23.3)); // 23 console.log(Math.trunc(23.9)); // 23 console.log(Math.trunc(23)); // 23
// Date(year: number, monthIndex: number, date?: number | undefined, hours?: number | undefined, minutes?: number | undefined, seconds?: number | undefined, ms?: number | undefined): Date // The full year designation is required for cross-century date accuracy. If year is between 0 and 99 is used, then year is assumed to be 1900 + year. // Thu Nov 19 2037 15:52:12 GMT+0800 (中国标准时间) console.log(newDate(2037, 10, 19, 15, 52, 12));
// setTimeout(handler: TimerHandler, timeout?: number | undefined, ...arguments: any[]): number // 3000 -> 3s // the code is not stop here // Waiting... // Here is your pizza setTimeout(function () { console.log('Here is your pizza'); }, 3000); console.log('Waiting...');
// Here is your pizza with olives and spinach setTimeout(function (ing1, ing2) { console.log(`Here is your pizza with ${ing1} and ${ing2}`); }, 3000, 'olives', 'spinach');
const ingredients = ['olives', 'spinach'];
const pizzaTimer = setTimeout(function (ing1, ing2) { console.log(`Here is your pizza with ${ing1} and ${ing2}`); }, 3000, ...ingredients);
console.log(pizzaTimer); // 4 if (ingredients.includes('spinach')) clearTimeout(pizzaTimer)
const startLogoutTimer = function () { const tick = function () { const min = String(Math.floor(time / 60)).padStart(2, 0); const sec = String(time % 60).padStart(2, 0);
// print the remaining time to the ui labelTimer.textContent = `${min}: ${sec}`;
// when 0 seconds, stop timer and logout user if (time === 0) { clearInterval(timer); labelWelcome.textContent = 'LOG IN TO GET STARTED'; containerApp.style.opacity = 0;
}
time--; }
// set time to 5 mins let time = 120;
// call the timer every second tick(); const timer = setInterval(tick, 1000); return timer; }
1 2 3 4 5
let timer; btnLogin.addEventListener('click', function (e) { if (timer) clearInterval(timer) timer = startLogoutTimer(); });
advanced DOM and EVENT
DOM deep
allows us to make javascript interact with the browser;
we can write javascript to create, modify and delete Html elements; set styles, classes and attributes; and listen and respond to events;
dom tree is generated from an html document, which can then interac with;
dom is a very complex api(application programming interface) that contains lots of methods and properties to interact with the dom tree
// Returns the first element that is a descendant of node that matches selectors. const header = document.querySelector('.header'); // NodeList const allSections = document.querySelectorAll('.section'); console.log(allSections);
console.log(document.getElementById('section--1')); // HTMLCollection ---> live collection console.log(document.getElementsByTagName('button')); // HTMLCollection console.log(document.getElementsByClassName('btn'));
// create and insert elements
// .insertAdjacentHTML()
// Creates an instance of the element for the specified tag. const message = document.createElement('div'); // classList: Allows for manipulation of element's class content attribute as a set of whitespace-separated tokens through a DOMTokenList object. message.classList.add('cookie-message'); message.textContent = 'We use cookied ....';
message.innerHTML = 'We use cookied ....<button class="btn btn--close-cookie">Got it!</button>';
// Inserts nodes before the first child of node, while replacing strings in nodes with equivalent Text nodes. header.prepend(message); // append: Inserts nodes after the last child of node, while replacing strings in nodes with equivalent Text nodes. ///// if it is used twice it is moved, not copy // cloneNode: Returns a copy of node. If deep is true, the copy also includes the node's descendants. header.append(message.cloneNode(true));
// Inserts nodes just after node, while replacing strings in nodes with equivalent Text nodes. header.after(message); // Inserts nodes just before node, while replacing strings in nodes with equivalent Text nodes. header.before(message)
const logo = document.querySelector('.nav__logo');
///// element standard attributes/property // Bankist logo console.log(logo.alt); /// full path // http://127.0.0.1:5500/complete-javascript-course-master/13-Advanced-DOM-Bankist/starter/img/logo.png console.log(logo.src); // nav__logo console.log(logo.className);
logo.alt = 'Beautiful minimalist logo'
//// non standard attributes/property
// Returns element's first attribute whose qualified name is qualifiedName, console.log(logo.getAttribute('designer')); // lucfe // relative path: img/logo.png console.log(logo.getAttribute('src'));
// (method) Element.setAttribute(qualifiedName: string, value: string): void // Sets the value of element's first attribute whose qualified name is qualifiedName to value. logo.setAttribute('designer', 'jonas');
const link = document.querySelector('.nav__link--btn') console.log(link.href);// http://127.0.0.1:5500/complete-javascript-course-master/13-Advanced-DOM-Bankist/starter/index.html# console.log(link.getAttribute('href')); //
/// data attributes // data-version-number="3.0" console.log(logo.dataset.versionNumber); // 3.0
/// classList: // (property) Element.classList: DOMTokenList // Allows for manipulation of element's class content attribute as a set of whitespace-separated tokens through a DOMTokenList object.
// Adds all arguments passed, except those already present. logo.classList.add('c', 'j'); // Adds all arguments passed, except those already present. logo.classList.remove('c'); // If force is not given, "toggles" token, removing it if it's present and adding it if it's not present. logo.classList.toggle('c'); // (method) DOMTokenList.contains(token: string): boolean // Returns true if token is present, and false otherwise. logo.classList.contains('c');
// !!! dont use/// erase all classes // logo.className = 'jonas'
smooth scrolling
1 2 3 4 5
<divclass="header__title"> <buttonclass="btn--text btn--scroll-to">Learn more ↓</button> </div> <sectionclass="section"id="section--1"> </section>
// height/width of the viewport 573 1221 console.log('height/width of the viewport', document.documentElement.clientHeight, document.documentElement.clientWidth);
// scrolling relative to the viewport // window.scrollTo(s1coords.left + window.pageXOffset, s1coords.top + window.pageYOffset);
const alertH1 = function (e) { alert('addEventListener: your are reading the heading');
// Removes the event listener in target's event listener list with the same type, callback, and options. h1.removeEventListener('mouseenter', alertH1) }
/// like mouse hover /// can add multible eventhandlers /// Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched. h1.addEventListener('mouseenter', alertH1);
document.querySelector('.nav__link').addEventListener('click', function (e) { console.log('nav__link'); this.style.backgroundColor = randomColor();
// <a> element console.log('LINK', e.target);
// stop progagation // When dispatched in a tree, invoking this method prevents event from reaching any objects other than the current object. // e.stopPropagation();
// When set to true, options's capture prevents callback from being invoked when the event's eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event's eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event's eventPhase attribute value is AT_TARGET. }, true) document.querySelector('.nav__links').addEventListener('click', function (e) { console.log('nav__links'); this.style.backgroundColor = randomColor();
// <a> element console.log('LINKs', e.target);
/// this === e.currentTarget // <ul> console.log('Links', e.currentTarget); }) document.querySelector('.nav').addEventListener('click', function (e) { console.log('nav'); this.style.backgroundColor = randomColor();
// 1. add event listenner to comon parent elemetnt // 2. determine what element originated the event document.querySelector('.nav__links').addEventListener('click', function (e) { console.log(e.target);
e.preventDefault();
// mathing startegy if (e.target.classList.contains('nav__link')) { console.log('LINK');
// Returns the first (starting at element) inclusive ancestor that matches selectors, and null otherwise. /// reverse directiong of querySelector // element: header.header console.log(h1.closest('.header')); // element: h1 console.log(h1.closest('h1'));
<div class="operations__content operations__content--1 operations__content--active" > <divclass="operations__icon operations__icon--1"> </div> <h5class="operations__header"> Tranfser money to anyone, instantly! No fees, no BS. </h5> <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. </p> </div> ... </div>
tabsContainer.addEventListener('click', e => { e.preventDefault(); const clicked = e.target.closest('button'); console.log(clicked);
/// guard clause if (!clicked) return;
/// remove active class and add active tab tabs.forEach(t => t.classList.remove('operations__tab--active')); clicked.classList.add('operations__tab--active');
/// active content area tabsContent.forEach(content => { content.classList.remove('operations__content--active') }); document.querySelector(`.operations__content--${clicked.dataset.tab}`).classList.add('operations__content--active');
///provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document's viewport.
// replace the src img with data-src entry.target.src = entry.target.dataset.src;
// remove the filter css class // should wait the image all loaded the remove the filter class // entry.target.classList.remove('lazy-img'); entry.target.addEventListener('load', e => { entry.target.classList.remove('lazy-img'); });
// remove the observer observer.unobserve(entry.target); }
document.addEventListener('keydown', function (e) { // console.log(e); if (e.key === 'ArrowLeft') { preSlide(); } elseif (e.key === 'ArrowRight') { nextSlide(); }
});
dotContainer.addEventListener('click', function (e) { e.preventDefault(); const clicked = e.target; if (clicked.classList.contains('dots__dot')) { goToSlide(clicked.dataset.slide);
/// active dot activateDot(clicked.dataset.slide);
} })
}
slider();
DOM load event
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// html and js downloaded document.addEventListener('DOMContentLoaded', function (e) { console.log(e); console.log(e.timeStamp); });
/// all resources loaded, include css, images window.addEventListener('load', function (e) { console.log(e); });
/// before user leave the page, like: close the tab // window.addEventListener('beforeunload', function (e) { // e.preventDefault(); // console.log(e); // e.returnValue = ''; // })
js loading and execude
OOP
what is OOP?
oop is a programming paradigm based on the concept of objects
we use objects to model(describe) real world or abstract features
object may contain data(properties) and code (methods). by using objects, we pack data and the corresponding behavior into one block;
in oop, objects are self-contained pieces/ blocks of code
objects are building blocks of applicatins, and interact with one another;
interactions happen through a pubblic interface (API): methods that the code outside of the object can access and use to communicate with the object;
OOP was developed with the goal of organizing code, to make it more flexible and easier to maintain(avoid ‘spaghetti code’)
Abstraction: Ignoring or hiding details that dont matter, allowing us to get an overview perspective of the thing we’re implementing, instead of messing with details that don’t really matter to our implementation.
Encapsulation: Keeping properties and methos private inside the class, so they are not accessible from outside the class. Some methods cas be exposed as a public interface(API)
Inheritance: Making all properties and methods of a certain class available to a child class, forming a hierarchical relationshipp between classes. This allows us to reuse commmon logic and to model real world relationships.
Polymorphism: A child class can overwrite a method it inherited from a parent class.
javascript OOP
Objects are linked to a prototype object;
Prototypal inheritance: The prototype contains methods (behavior) that are accessible to all objects linked to that prototype;
behavior is delegated(授权) to the linked prototype object.
3 ways of implementing prototypal inheritance in javascript
Constructor funtions
Technique to create objects from a function;
This is how built-in objects like Arrays, Maps or Sets are actually implemented.
ES6 Classes
Modern alternative to constructor function syntax;
‘Syntactic sugar’: behind the scenes, ES6 classes work exactly like constructor functions
ES6 clasees do not behavior like classes in “classical OOP”
Object.create()
the easiest and most straightforward way of linking an object to a prototype object.
// /// dont do this// // /// the object new create will all have the same copy function // this.clacAge = function(){ // console.log(2037 - this.birthYear); // }
}
const jonas = newPerson('Jonas', 1991); // Person {firstName: 'Jonas', birthYear: 1991} console.log(jonas);
// 1. new object {} is created // 2. function is called, this is point to the new object {} // 3. the new object {} is linked to prototype // 4. function automatically return the new object {}
//// all function have properties called prototype /// all the objects (the constructor function created ) have all the methods and properties ( the prototype object have)
////// example ////// dont do this in reality Array.prototype.unique = function () { return [...newSet(this)]; } // (7) [1, 2, 5, 47, 98, 74, 42] console.log(arr.unique());
console.log(jessica.fullName); // 'not a full name' // console.log(jessica.fullName = 'Jessica'); // 'not a full name' // const walter = new PersonCl('Walter', 1996);
EV.prototype.chargeBattery = function (chargeTo) { this.charge = chargeTo; };
EV.prototype.accelerate = function () { this.speed += 20; this.charge--; console.log(`${this.make} going at ${this.speed} km/h, with a charge of ${this.charge}%`); }
constStudentProto = Object.create(PersonProto); StudentProto.init = function (firstName, birthYear, course) { PersonProto.init.call(this, firstName, birthYear); this.course = course; } StudentProto.introduce = function () { console.log(`My name is ${this.firstName} and I study ${this.course}`); }
// Uncaught SyntaxError: Private field '#movements' must be declared in an enclosing class // acc1.#movements.push(250); // acc1.#movements.push(-140); // Uncaught SyntaxError: Private field '#approveLoan' must be declared in an enclosing class // acc1.#approveLoan(1000)
classPerson { constructor(fullName, birthYear) { this.fullName = fullName; this.birthYear = birthYear; } } // Child class and parent class // inheritance between classes, automatically sets prototype classStudentextendsPerson { // public field(similar to property, available on created object) university = 'University of London'; // private fields(not accessible outside of class) #studyHours = 0; #course; // static public field (available only on class) static numSubjects = 10;
// constructor method, called by new operator. mandatory(强制) in regular class, might be omitted in a child class constructor(fullName, birthYear, startYear, course) { // call to parent(super) class (necessary with extend).Need to happen before accessing this super(fullName, birthYear);
// instance property(available on created object) this.startYear = startYear;
// redefining private field this.#course = course; }
// public method introduce() { console.log(`I study ${this.#course} at ${this.university}`); }
study(h) { // referencing private field and method this.#makecoffe(); this.#studyHours += h; }
// private method(might not yet work in your browser. "fake" alternative: _ instead of #) #makecoffe() { return'Here is a coffee for you ' }
// setter method(use _ to set property with same name as method, and also add getter) settestScore(score) { this._testScore = score <= 20 ? score : 0; }
// static method(available only on class. can not access instance properties nor methods, only static ones) staticprintCurriculum() { console.log(`There are ${this.numSubjects} subjects`); } }
// creating new object with new operator const studentJonas = newStudent('Jonas', 2020, 2037, 'Medicine'); studentJonas.introduce(); // I study Medicine at University of London studentJonas.study(2); studentJonas.testScore = 36; console.log(studentJonas.testScore); // 0 console.log(Student.numSubjects) // 10 Student.printCurriculum();
Mapty app OOP project
project planning
user stories
description of the application’s functionality from the user’s perspective
common format: As a [type of user(who)], I want [an action(what)] so that [a benefit(why)]
example
as a user, i want to log my running workouts with location, distance, time, pace and steps/minute, so i can keep a log of all my running
as a user, i want to log my cycling workouts with location, distance, time, speed and elevtion gain, so i can keep a log of all my cycling
as a user i want to see all my workouts at a glance, so i can easily track my progress over time
as a user, i want to also see my workouts on a map, so i can easily check where i work out the most
as a user, i want to see all my workouts when i leave the app and come back later, so that i can keep using the app over time
features
user 1:
1.map where user clicks to add new workout(best way to get location coordinates)
2.geolocation to display map at current location(more user friendly)
3.form to input distance, time, pace, steps/minute
user 2: 4.form to input distance, time, speed, elevation gain
user 3: 5.display all workouts in a list
user 4: 6.display all workouts on the map
user 5:
7.store workout data in the browser using local storage API
8.on page load, read the saved data from local storage and display
flowchart
architecture
development
the geolacation api
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// Geolocation.getCurrentPosition(successCallback: PositionCallback, errorCallback?: PositionErrorCallback | null | undefined, options?: PositionOptions | undefined): void if (navigator.geolocation) { navigator.geolocation.getCurrentPosition( function (position) { // console.log(position); const { latitude, longitude } = position.coords; console.log(latitude, longitude); console.log(`https://www.google.com/maps/@${latitude},${longitude}`); }, function () { alert('Could not get your position') }); }
map.on('click', function (mapEvent) { console.log(mapEvent); const { latlng: { lat, lng } } = mapEvent; console.log(lat, lng);
L.marker([lat, lng]).addTo(map) .bindPopup(L.popup({ maxWidth: 250, minWidth: 100, // the popup closing when another popup is opened. autoClose: false, // the popup closing when user clicks on the map closeOnClick: false, // A custom CSS class name to assign to the popup. className: 'running-popup', })) // Sets the content of the popup bound to this layer. .setPopupContent('Workout') .openPopup(); });
/// display marker console.log(mapEvent); const { latlng: { lat, lng } } = mapEvent; console.log(lat, lng); L.marker([lat, lng]).addTo(map) .bindPopup(L.popup({ maxWidth: 250, minWidth: 100, // the popup closing when another popup is opened. autoClose: false, // the popup closing when user clicks on the map closeOnClick: false, // A custom CSS class name to assign to the popup. className: 'running-popup', })) // Sets the content of the popup bound to this layer. .setPopupContent('Workout') .openPopup(); });
inputType.addEventListener('change', function () { inputElevation.closest('.form__row').classList.toggle('form__row--hidden'); inputCadence.closest('.form__row').classList.toggle('form__row--hidden'); })
_getPostion() { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition( this._loadMap.bind(this), function () { alert('Could not get your position') }); } }
//// get data from form const type = inputType.value; // const distance = Number(inputDistance.value); // const duration = Number(inputDuration.value); const distance = +inputDistance.value; const duration = +inputDuration.value; const { latlng: { lat, lng } } = this.#mapEvent; const coords = [lat, lng]; let workout;
//// if workout is runnign, create running object if (type === 'running') { const cadence = +inputCadence.value; //// check the data is valid // if (!Number.isFinite(distance) || // !Number.isFinite(duration) || // !Number.isFinite(cadence)) // return alert('input should be a number'); if (!validInputs(distance, duration, cadence) || !allPositive(distance, duration, cadence)) returnalert('input should be a positive number');
//// if workout is runnign, create running object if (type === 'cycling') { const elevation = +inputElevation.value; if (!validInputs(distance, duration, elevation) || !allPositive(distance, duration)) returnalert('input should be a positive number');
/// load local storage workout on the map this.#workouts.forEach(work => {
this._renderWorkoutMarker(work); });
}
_setLocalStorage() {
// localStorage.setItem() // (method) Storage.setItem(key: string, value: string): void // Sets the value of the pair identified by key to value, creating a new key/value pair if none existed for key previously.
// JSON.stringify() // Converts a JavaScript value to a JavaScript Object Notation (JSON) string. localStorage.setItem('workouts', JSON.stringify(this.#workouts)); }
_getLocalStorage() { /// Converts a JavaScript Object Notation (JSON) string into an object. const data = JSON.parse(localStorage.getItem('workouts')); console.log(data);
_getPostion() { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition( this._loadMap.bind(this), function () { alert('Could not get your position') }); } }
//// if workout is runnign, create running object if (type === 'cycling') { const elevation = +inputElevation.value; if (!validInputs(distance, duration, elevation) || !allPositive(distance, duration)) returnalert('input should be a positive number');
Ajax: Asychronous Javascript and xml: allow us to communicate with remote web servers in an asynchronous way. with AJAx calls, we can request data from web servers dynamically.
API Application Programming Interface Piece of software that can be used by another piece of software, in order to allow applications to talk to each other;
Online API / Web API Application running on a server, that receives requests for data, and send data back as response; We can build our own web APIs(requires back-end development)
cors: Cross-origin resource sharing (CORS) is a browser security feature that allows access to restricted resources on a web page from another domain.
const getCountryData = function (country) { // Use XMLHttpRequest (XHR) objects to interact with servers. You can retrieve data from a URL without having to do a full page refresh. This enables a Web page to update just part of a page without disrupting what the user is doing. const request = newXMLHttpRequest();
promise: an object that is used as a placeholder for the future result of an asynchronous operation a container for an asynchronous delivered value a container for a future value
we no longer need to rely on events and callbacks passed into asynchronous functions to handle asynchronous results;
instead of nesting callbakcs, we can chain promises for a sequence of asynchronous operation: escaping callback hell;
// ////!!! dont do this // return fetch(`https://restcountries.com/v3.1/alpha/${neighbour}`).then().then(); }) .then(response => response.json()) .then(data =>renderCountry(data[0], 'neighbour'));
//(method) Promise<void>.catch<void>(onrejected?: ((reason: any) => void | PromiseLike<void>) | null | undefined): Promise<void> /// handling all the error from the first promise .catch(err => { console.log(err); renderError(`Something went wrong ${err.message}`) });
//(method) Promise<void>.finally(onfinally?: (() => void) | null | undefined): Promise<void> // Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The resolved value cannot be modified from the callback. .finally(() => { countriesContainer.style.opacity = 1
});
throwing error manually
throwing error manually will be catch by the last catch() callback;
/// var Promise: PromiseConstructor // new <any>(executor: (resolve: (value: any) => void, reject: (reason?: any) => void) => void) => Promise<any> // A callback used to initialize the promise. This callback is passed two arguments: a resolve callback used to resolve the promise with a value or the result of another promise, and a reject callback used to reject the promise with a provided reason or error. const lotteryPromise = newPromise(function (resolve, reject) { console.log('Lotter draw is happening'); setTimeout(function () { if (Math.random() >= 0.5) { resolve('You win 10000$'); } else { reject(newError('You lost your money')); } }, 2000); });
// country data const res = awaitfetch(`https://restcountries.com/v3.1/alpha/${dataGeo.prov}`); console.log(res); const data = await res.json(); console.log(data); renderCountry(data[0]); };
// (method) PromiseConstructor.all<[Promise<any>, Promise<any>, Promise<any>]>(values: [Promise<any>, Promise<any>, Promise<any>]): Promise<[any, any, any]> (+1 overload) // Creates a Promise that is resolved with an array of results when all of the provided Promises resolve, or rejected when any Promise is rejected. const data = awaitPromise.all([ getJSON(`https://restcountries.com/v3.1/name/${c1}`), getJSON(`https://restcountries.com/v3.1/name/${c2}`), getJSON(`https://restcountries.com/v3.1/name/${c3}`)]);
//// Promise.race //// Creates a Promise that is resolved or rejected when any of the provided Promises are resolved or rejected. (asyncfunction () { const res = awaitPromise.race([ getJSON(`https://restcountries.com/v3.1/name/italy`), getJSON(`https://restcountries.com/v3.1/name/egypt`), getJSON(`https://restcountries.com/v3.1/name/mexico`) ]); console.log(res); })();
///example const timeout = function (sec) { returnnewPromise((_, reject) => { setTimeout(() => { reject(newError('Request took too long!')); }, sec * 1000); }); };
(asyncfunction () { const result = awaitPromise.race([ getJSON(`https://restcountries.com/v3.1/name/mexico`), timeout(1), ])
console.log(result); })();
/// Promise.allSettled /// Creates a Promise that is resolved with an array of results when all of the provided Promises resolve or reject. Promise.allSettled([ Promise.resolve('Sucess'), Promise.resolve('Error'), Promise.resolve('Anotrher result'), ]).then(res =>console.log(res));
//// the first fullfilled promise Promise.any([ Promise.resolve('Sucess'), Promise.resolve('Error'), Promise.resolve('Anotrher result'), ]).then(res =>console.log(res));