Web Dev Cookbook


Callbacks & Array Methods

Map function

The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.

example 1

const array1 = [1, 4, 9, 16];
//pass a function to map
const map1 = array1.map(x => x * 2);
// expected output: Array [2, 8, 18, 32]

example 2

text = [" timot", "    dart", "sass    ", " e Jo"]
const cleanName = function(x){
return x.map(function(t){
return t.trim()
})
}

Arrow functions

const add = (x,y) => {
    return x+y
}

Implicit Return (only works with 1 statement in the function)

const rollDie = () => (
    Math.random() * 6 + 1 
)
const add = (a,b) => a + b

Scheduling execution

Set Timeout

setTimeout(() =>(
console.log('Hello')), 3000)

Set Interval Repeat function at set intervals

setInterval( () => (
    console.log(Math.random())
))

Clear Interval

const id = setInterval( () => (
    console.log(Math.random())
)) 
clearInterval(id)

Filter

numbers.filter( n => {
    return n < 4)
    })

Every

Some

Reduce

Newer JavaScript Features

Default Parameters

function multiply (a, b = 5){
    return...
}

Spread in function call

const nums = [12, 3, 5, 6]
Math.max(...nums)

Spread in array

const allPets = [...dogs, ...cats]

Spread in Object Literals

Useful when creating copy of objects with additional properties (take data from a form and add extra data (admin rights, userId…))

const feline = { legs: 4, family: 'felix' };
const canine = { isFurry: true, family: 'dogs'};
{ ...feline, color: 'black' }

Rest

function sum(){
    console.log(arguments)  //I can pass as many args I want when calling sum (it is not an array -> use rest)
}

function sum(...nums) {
    return console.log(nums) //nums is an array
}

Destructuring Arrays

const scores = [10, 8, 6, 4];
const [gold, silver, ...everyoneElse] = scores;   //gold = 10, silver = 8

Destructuring Objects

const user = {
    email:  ;
    password:   ;
    fisrtName:  ;
    lastName:   ;
    born:     ;
}
const {email} = user;   //equivalent to const email = user.email
const { born: birthYear = "N/A"} = user; //rename variable and assign default values

Destructuring Params

function fullName(user){
    return `${user.firstName}, ${user.lastName}`
}

function fullName({firstName, lastName = 'aaa'}){
    return `${user.firstName}, ${user.lastName}`
   }

DOM

JS representation of a webpage.

const allImages = document.getElementsByTagName('img')
for (let image of allImages){
    img. ...
}

Query selector

document.querySelector('h1') //works with class, tags, ids (must use a css selector!). Return the first match
document.querySelectorAll('h1') //selects all

ClassList

h2.classList.add('aaa')
h2.classList.remove('bbb')
h2.classList.contains('red')
h2.classList.toggle('purple')

Change events

form.addEventListener('submit', function(e) {
    e.preventDefault(); \\stop the form from being sent
})

Event bubbling

form.addEventListener('submit', function(e) {
    e.stopPropagation(); \\stop the nested clicking from happening
})

Event Delegation

const container = document.querySelector('ui');

container.addEventListener('click', function(e) {
    e.target.remove() //item clicked
})

Use Bulma instead of Bootstrap

Async JS

The call stack

  • Mechanism that JS uses to keep track where it is in a script. Last thing in, first thing out.
  • To see the call stack in action use Sources in Chrome

Web API and Single Threaded

  • http://latentflip.com/loupe
  • JS is single threaded
  • The browser come with web API that can handle tasks in background
  • setTimeout is a web api function (-> callback function)
  • callback is used to delay execution

Promises

  • Objects that represents the eventual completion or failure of an asynchronous operation
  • Attach callback to the promise instead of passing them into a function
const request = dummyReqPromise('google.com/api')
request.then( (data) => {
    console.log('PROMISE 1 RESOLVED')
    console.log(data)
})
.then( (data) => {
    console.log('PROMISE 2 RESOLVED')
})
.then( (data) => {
    console.log('PROMISE 3 RESOLVED')
})
.catch( (err) => {
    console.log('PROMISED REJECTED')
    console.log(err)
})

Creating promises

const fakeRequest = (url) =>{
    return new Promise((resolve, reject)=>{
        setTimeout(() => {
            resolve('something');
        }, 1000);
    })        
}

fakeRequest('/cats/1')
    .then( (data) => {
        console.log("Done with request")
        console.log(data)
    })

Async Function

  • async functions always return a promise
const asyncFunction = async () => {
    //returns a promise
    return 'aaaa' //resolved value
}
  • to reject a promise: throw an error
    const asyncFunction = async () => {
      throw 'random error'
    }
    
  • login example ```chsarp const login = async (username, password) => { if (!username || !password) throw ‘Missing Credentials’ if (password === ‘1234’) return ‘Welcome’ throw ‘Invalid Password’; }

login(‘aaa’, ‘1234’) .then(msg => { console.log(‘logged in’); console.log(msg); }) .catch(err =>{ console.log(“error”) console.log(err) })


### Await keyword

- wait for a promise to be resolved before continuing with the async function
```csharp
const changeBackColor = (color, delay) =>{
    return new Promise((resolve, reject) =>{
        setTimeout( () => {
            document.body.style.backgroundColor = color;
            resolve();
        }, delay)
    }

    )
}

async function rainbow(){
    await changeBackColor('red', 1000)
    await changeBackColor('blue', 1000)
    await changeBackColor('green', 1000)
}

Rejected Promised

  const fakeRequest = (url) =>{
    return new Promise((resolve, reject) => {
        const delay = Math.floor(Math.random() * 4500)+500;
        setTimeout(() => {
           if (delay > 4000) {
               reject ('connection timeout')
           }
           else{
               resolve (`here is your data ${url}`)
           }
        }, delay);
    })
}


async function makeTwoRequests(){
    try{
        let data1 = await fakeRequest('/apple1')
        console.log(data1)
        let data2 = await fakeRequest('/apple2')
        console.log(data2)
    }   
    catch(e){
        console.log('error is', e);
    }
}

AsyncJavascriptAndXml requests

  • make request after the page has been loaded
  • jsonformatter.curiousconcept.com
  • JSON.parse(data) converts a string into json object

Fetch API

  • fetch returns a promise:
fetch('https://api.google.com')
    .then(res => { 
        console.log("RESPONSE", res)
        return res.json();
    })
    .then( data => {
        console.log(data.ticker.price);
    })
    .catch(e => {
        console.log('error');
    })
  • using async function:
const fetchBitcoinPrice = async () => {
try{
    const res = await fetch('https://api.google.com');
    const data = await res.json();
    console.log(data.ticker.price);
    }
catch(e){
    console.log(e);
    }
}

Axios

  • easier than use fetch
axios.get('https://api.cryptonator.com/api/ticker/btc-usd')
    .then( res => {
        console.log(res.data.ticker.price);
    })
    .catch( err => {
        console.log("Error", err);
    })
const fetchBTCPrice = async () => {
    try{
        const res = await axios.get('https://api.cryptonator.com/api/ticker/btc-usd');
        console.log(res.data.ticker.price);
    }
    catch (e) {
        console.log("Error", e);
    }
}

Setting Headers

  • set headers to get desired response type (html, json…)
const getDadJoke = async () => {
    const config = {headers:{Accept: 'application/json'}}
    const res = await axios.get('https://icanhazdadjoke.com/', config);
    return res.data.joke;
}

const jokeBtn = document.querySelector('#jokeBtn')
const jokeText = document.querySelector('#jokeText')

jokeBtn.addEventListener('click', async () => {
    try{
        await console.log('clicked')
        await getDadJoke().then(res => {            
            jokeText.textContent = res;
        });
    }
    catch(err){
        jokeText.textContent = "Error joke not available";
    }
    })    

Prototypes, Classes and OOP

Prototypes

function Person(first, last, age, gender, interests) {
  this.name = {
    'first': first,
    'last' : last
  };
  this.age = age;
  this.gender = gender;
}

  • Prototypes are the mechanism by which JavaScript objects inherit features from one another.
  • if you call a method on person1 that is defined on Object.prototype (i.e. person1.ValueOf()) the browser initially checks to see if the person1 object has a valueOf() method available on it, as defined on its constructor, Person(), and it doesn’t. So the browser checks to see if the person1’s prototype object has a valueOf() method available on it. It doesn’t, then the browser checks person1’s prototype object’s prototype object, and it has. So the method is called, and all is good!

Factory Functions

javascript-factory-functions A factory function is a function that returns a new object.

The following creates a person object named john:

let john = {
    firstName: 'John',
    lastName: 'Doe',
    getFullName() {
        return this.firstName + ' ' + this.lastName;
    }
};

The more object you want to create, the more duplicate code you need to copy. To avoid copying the same code all over again and again, you can develop a function that creates the person object:

function createPerson(firstName, lastName) {
    return {
        firstName: firstName,
        lastName: lastName,
        getFullName() {
            return firstName + ' ' + lastName;
        }
    }
}

To avoid repeating the same getFullName() function in the memory, you can remove the getFullName() method from the person object and move this method to another object:

const behavior = {
    getFullName() {
        return this.firstName + ' ' + this.lastName;
    }
}

And before calling the getFullName() method on the person object, you can assign the method of the behavior object to the person object as follows:

let john = createPerson('John', 'Doe'),
john.getFullName = behavior.getFullName;
console.log(john.getFullName());

It’ll more difficult if you have many methods and have to assign them manually. This is why the Object.create() method comes into play.

function createPerson(firstName, lastName) {
    let person = Object.create(behavior);
    person.firstName = firstName;
    person.lastName = lastName;
    return person;
}

In practice, you will rarely see the factory functions. Instead, you will see the function constructors or the classes.

Constructor Functions

what-are-javascript-constructor-functions

function Person(name, age) {
  this.name = name;
  this.age = age;
    this.greet = function(){
   return `Hi ${this.name}`;
  }
}

this is an object that has the data of the object instance created by the new keyword. With this function, we can create a new Person object by writing:

let person = new Person('Joe', 10);

In the Person function, this.name and this.age are properties of object instances that are created with the new operator. this.name of the person object would have the value ‘Joe’, and this.age would have the value 10.

Classes

class Person {
    constructor(name) {
        this.name = name;
    }
    getName() {
        return this.name;
    }
}

Extends and Super Keywords

The extends keyword is used in class declarations or class expressions to create a class that is a child of another class.

The super keyword is used to access and call functions on an object’s parent. When used in a constructor, the super keyword appears alone and must be used before the this keyword is used.

class Pet {
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
    eat(){
        return `${this.name} is eating`;
    }
}
class Cat extends Pet {
    constructor (name, age, livesLeft = 9){
        super(name, age);
        this.livesLeft = livesLeft;
    }
    meow(){
        return 'miao';
    }
}

Terminal

  • Shell program running on a terminal
  • Bash an emulator for running Unix shell on Windows

Commands

  • ls list director
  • pwd print working directory
  • cd change directory
  • cd.. back one level
  • absolute path starts with / i.e.: cd /Users/Documents and cd ../../Documents
  • mkdir make directory
  • man manual: man ls
  • touch make new file
  • rm FileName remove file
  • rmdir FolderName remove directory (only if it is empty)
  • rm -rf FolderName delete recursive and force (when folder is not empty)

Node JS

A Javascript runtime (run Javascript outside the browser).

  • Web Servers
  • Command Line Tools (npm)
  • Native apps
  • node FileName.js execute file

Process

The process object provides information about, and control over, the current Node.js process.

  • process.argv returns an array containing the command-line arguments passed when the Node.js process was launched. The first element will be process.execPath. See process.argv0 if access to the original value of argv[0] is needed. The second element will be the path to the JavaScript file being executed. The remaining elements will be any additional command-line arguments.
  • process.cwd() returns the current working directory of the Node.js process.
const fs = require('fs');

//console.log(fs);
fs.mkdir('apple', {recursive: true}, (err) => {
    console.log("in the callback")
});

fs.mkdir.mkdirSync('Cats');

Get user input:

const fs = require('fs');
const folderName = process.argv[2]

fs.mkdir.mkdirSync(folderName);

Modules

Written on March 26, 2021