Javascript Fundamentals

Javascript is a High level, interpreted programming language that doesn't have to run through a compilier. The language controls the interactivity of a page such as showing or hiding objects, scrolling, pop ups, whatever you can click or control or animate objects on a page, submit info or respond to small queries such as form validation. Javascript is case sensitive. Keep the javascript content at the bottom before the </body> part of the document so the HTML portion can load faster. syntax follows [prompt ();] would be the verbs.

It doesn't take consideration of any memory manage on the machine. It's multi-paradigm, meaning that you can write your code in many different ways and is flexible in how you write your code. It can run on the client/bbrowser or on a server(javascript runtime Node.js) to interact with databases.

Javascript is the programming langauge of the browser and is a good focus if you want to learn client-side programming. Other languages generally don't run things clientside unless there's a library for the language to reference that generates the code for the browser. Generally used to build interactive user interfaces with frameworks like React, Angular, VueJS.

The language can be used to build very fast server side and full stack applications using Node.JS. Can be used to build mobile apps like React Native, NativeScript, or Ionic or build desktop apps with frameworks like Electron JS.

Javascript functions different from other languages as its arrays are not statically typed, as in it doesn't differentiate between data types. You can have the data type is a strings or numbers and you don't have to categorize them like other languages unless you're using Typescript.

Javascript can be placed internally inside an HTML document using <script> tag

Javascript Linting Tools; code quality checking tools. Brackets text editor uses JSLint and ESLint. Will highlight errors, could be syntax errors.

Javascript Events are things a browser or user does to have HTML elements have interactivity to occur.
Event listeners wait for an event to occur to respond. Could be onclick.

** A good place to learn about Javascript is MDN Web Docs

Commands & Commenting in Javascript:

Console commands are formatted as console.command('String');

'Properties' do not have parenthesis, if there is parenthesis than it is a 'method'. Methods are functions associated with an object.
console.log(var.length); only has a property while console.log(var.toUpperCase()); includes a method

Syntax for the console log is as follows:
console.log(container.varName.embeddedObject[index#]
or you can do the following 'destructuring' method to create a variable out of existing object: const {firstName, lastName, address: { city }} = person;

You can add properties that weren't included in container:
Ex: varName.email = 'johndoe@mail.com';

Javascript like CSS can be added to a webpage internally, externally, or inline. They're linked either in the head or at the end of the body just before the closing tag using the '<script>' tag. Like CSS, it will load sequentially line by line.

                <script src="./location/script.js"></script>      //an example of linking JS externally
            
                <buttonhref="#" onClick="alert ('Clicked')"> Click Here </button>    //inline JS
            

Just like CSS, it's easier to read and maintain external Javascript files. It is faster for cached JS files to load and helpful for reuseable code. The downsides to have the external JS file are that the browser must make an extra HTTP request to get the code, the JS file can be downloaded using the URL, and if there are dependant files and then when one of the dependencies fails, it may affect the other files. Pages will load faster the less script tags there are on a page.

Even in inline JavaScript, HTML code is prioritized. However, when there's both internal and external Javascript being presented, the internal embedded code will be overridden. The positive side is that Inline and Internal javascript will be executed immediately and is helpful using server-side dynamic rendering but not not allow for reusable code.

                <noscript>Browser does not support Javascript<noscript>
            

Basic Syntax

            Syntax Example; 
            var firstNumber = 7;
            var secondNumber = 8;
            var addNumbers = firstNumber+secondNumber;
        

Variables are containers for storing data values. var is a globally scoped keyword used to declare variables. This means that if you have a conditional if statement and you set a variable in the statement and then outside of the block there's another variable with the same name, it can cause a conflict.
let is a keyword that was added later that lets you reassign values; For example: let age = 30; then you can reassign the variable to age = 32; without an error.
'const' is short for constant which means that the value cannot be reassigned. Always use 'const' unless you know you're going to reassign the value.
'=' is an assignment operator to assign value. value 7 is stored in the container firstNumber.
var x = 7; number
var myCar='Porche'; you need '' to indicate that it's a string

Undefined statements; myCar ='Range Rover'; will change the value of the variable moving forward.

Variable names cannot start with a number or punctuation mark. You can not use operators such as =,+, or - variable names cannot contain spaces and they're case-sensitive. You cannot use JavaScript Keywords because it's a part of the language.
Example; Window; open, string but you can have myWindow or myString

An example for when 'let' is better to use instead of const:

            let score;

            score = 7;
            
            console.log(score);
        

let score; initializes the program, but if you're unable to do so if you use 'const' as it will return a SyntaxError as it is missing an initializer in the const declaration and you need to have a declared value such as 'const score = 10;'.

Generally when you're working with arrays and objects, the values within them can be reassigned.

            Example: 
            <script>
            
            var myHeading = document.querySelector('h1')
            
            myHeading.textContent= "Be Smart!"
            
            </script> 
        

or externally with a .js file extension. You need to create a reference.
For Example: <script src="scripts/myscript.js"></script>

In Javascript; in the command console; a popup box is created in an alert function.

Developer Tool Console; powerful free tools for debugging your code. You can experiment with JavaScript in the console. Most web browsers have a developer console. There are different ways to access the tool. Right-click on a space on a webpage and choose to inspect the element. Or Alt+Command+I for Mac; Ctrl + Shift + i for windows. Or F12

            Example: 
            var firstNumber = 27;
            
            var secondNumber = 47;
            
            var addNumbers = firstNumber + secondNumber;

            alert(addNumbers);
        

This will have return the value of 74 in an alert popup: This page says 74 with an OK button. You can have console.log(addNumbers); will have it display in the console.

prompt(); is a function that can be used to get data from the user.
You can get the computer to enter the variable.

                Ex:
                var firstName = prompt(“Enter your first name:)”
                var greeting = “Hello ” + firstName;
            

This will prompt you to input your name.

Arrays & Object Literals

Arrays are a structure that allows you to store multiple values in a single reference. You can have different data types in an array. This is fine in javascript but in other languages it's generally better to have the same data type included in the array and possibly assign it with a number. Javascript is not statically typed (Ex name:string) like Typescript which is like a superset of Javascript with added features.

Object literals are key value pairs

'New' is an array constructor using the old method.

 
            const numbers = new Array(1,2,3,4);
        
            console.log(numbers); 
            
            This will generate an array with values 1-4. 
        
            You don't need a data constructor to create an array when using brackets. Example: 
            const myData = [7, 'John', 'Jane', 17];
        

This will return 4 lines in the console with the index values in the brackets starting with 0.

Adding an array is a method called 'pushing' and 'popping' will remove the last value in the array. You can also use 'unshift' to add a value to the start of the array.

            Example: 
            const fruits = ['apples', 'bananas', 'oranges'];
            
            fruits.push('pineapples');
        

this function adds 'pineapples' to the container 'fruits'. You can also use the following method to add and assign a value to the array:

fruits[4] = 'grapes'
Example: fruits.pop();

this function will remove the last value entered

console.log(fruits[1]);

This will call the value 'bananas' as index numbers count from 0.

**Reminder: You cannot reassign an array using the 'const' otherwise you get returned an error. Generally you manipulate data in an array and you don't reassign it. In order reassign the array, the array has to be created using 'var'.
Ex: var fruits = ['apples', 'bananas', 'oranges'];
fruits = [];

In order to check the index of a value, you would use the following console command:

console.log(fruits.indexOf('oranges;);

This will return the index value of 3 based on the location of the string in the array.

In order to check of an array is in an array, use the following console command:

console.log(Array.isArray(variableName));

This creates a boolean that will return a true or false value. Generally used in conjuctions with conditionals.

Modules

Used to bring everything together and import files, packets, or pieces of code into another file. They are not supported in browsers directly so you have to use tools such as Parcel or Webpack with Babel.

Classes

Classes are a term used in multiple languages. Used mostly in React & Angular

Destructuring

Preferred when you look at most frameworks, makes for cleaner and more readable code. Unpack values from objects and arrays.

            Examples: 
            const { name, email } = user;
            
            const { name, email, address: {city} } = user;
        

We have a user object with some fields to put into a variable. The first example is done so you can get a name and email for a variable in the user object. The second is done so you can pull the address object and you can pull the city which is the property of the address object within the 'user'

Concept of Components & State

UIs are broken up into individual components which has some sort of state associated with them. You are taught about separation of concerns for the HTML mark up, CSS stying, and the Javascript for any dynamic type functionality where you select elements from the DOM. The difference for mindsets using Frameworks is that you start thinking of each user interface as individual components that are encapsulated entities that include both markup/disply and the functionality. Each component can have its own data and state of being.

Application level states are usually implement using a state manager like Redux, Vuex, etc

Nested components (Parent & children)

Can be directly inserted or used in a router. 'State' is a React object that is used to contain information about the component. When the component's state changes, then the component re-renders.

For example, if you look at a website, there can be a search bar as a component, another one that tracks statistics, another one that tracks activities, or suggestions for other users for UI when dealing with frameworks. When you share state you look into something like React for Redux or Vuex for Vue for state level management when sharing data for a single source of truth or context API, Graph QL & Apollo. There are different technologies to use.

Spread Operator (...)

State is usually unchangeable or immutable so it cannot be direclty changed. The spread operator allows us to make a copy to add what we want and change what we want and then send it to the application or component.

            Examples: 
            const userState = {
                name: 'Jane'
            }
            
            const newUserState = {
                ...userState,
                age: 28
            }
        

This user state has one property of 'name' that represented by Jane and you add a new user state using the spread operator (...) to make a copy of the userState then add the age property.

Data Types & Methods for Strings, Arrays, Objects, etc

Data types are types of data assigned to variables. There are primitive data types where the data is directly assigned to memory and not a resource.

In order to test and identify data types in javascript use the following:

console.log(typeof variablename);

**the only exception is that NULL values are defined as an object data type due to it being a typetag and objects being 0. As a result, null had 0 as a type tag which returns it as an object in the console.

Concatenation is a series of interconnected things or events. When used in relation to language theory and computer programming, string concacternation is the combination of character strings rom end to end.
Old Method Ex: console.log('My name is ' + name + 'and my favourite color is ' + color);

Template Stings or Literals were introduced as a new method during ES6 or ES2015
Newer Method Ex: console.log(`My name is ${name} and I am ${age}`);

This can also be used to define a variable.

            const greeting = `My name is ${name} and I am ${age}`;
            
            console.log(greeting);
        

Operators

Conditional Statements (if, ternary & switch)

Functions (normal & arrow)

Callback Functions & Event Listeners

'callback' functions are functions that have been nested into another function as an argument which is then called inside the outter or parent function to complete.

When you want to create a 'callback' function, you pass the function inside another function as a parameter. Javascript loads the full script first then runs code sequentially from top to bottom.

Callbacks make sure that a function will not run before a task is completed and will run after a task or condition is met. This is called asynchronous programming.

            function first () {} //declares the function name
            function second (callback) {  //received first function as a parameter
                console.log(callback){}  //logs function first () {}
            }

            second(first)
        
            function logWord () {
                console.log('Something')
            }
            run(logWord)

            is the same as: 
            run(function() {
                console.log('Something')
            })
        

'Anonymous' functions are functions that have been defined in another function that don't require calling.

            setTimeout(function() {
                console.log('Response not received from server. Request timed out (30 seconds)');
            }, 30000);

            which is the same as: 
            setTimeout(() => {
                console.log('Response not received from server. Request timed out (30 seconds)');
            }, 30000);
        
Another Example: 
            function name(first, last) {
                return first + ' ' + last
            }
            let first = 'John'
            let last = 'Doe'
            console.log('My name is ' + (name(first, last)));
        

Event-listeners are methods or functions that exist generally pending user input or activity.

Callback functions can be used in conjunction with event-listeners.

            document.queryselector('#button-clicked')
            .addEventListener('click', function() { // function() would be the callback function.
                console.log('User clicked button.');
            });
        

Loops in Javascript

JavaScript Loops are used to run a block of code repeatedly until a certain condition is met

High Order Array Methods/Functions

Function that takes another function as a parameter. There following are commonly used functions that apply to arrays and are used oten to iterate through and manipulate data.

Arrays are objects stored in javascript which has keys that are assigned to functions/object methods. You can call high order array functions as a function or using '.' notation.

            let numbers = [2, 4, 6, 8]
            console.log('original array: ', numbers)
            console.log ('-----'
            
            let eachArray = []  //creates empty array
            let forEachNumbers = numbers.forEach(function(element, index){
                console.log(`.forEach Loop ${index}: `, element)        //returns Original Array: [2, 4, 6, 8]
                eachArray.push(element * 2)     //creates a function that performms the same as map 
            })
    
            let mappedNumbers = numbers.map(function(element, index) {
                console.log(`.map Loop ${index}: `, element)        //returns .forEach Loop 0: 2; .forEach Loop 1: 4; .forEach Loop 2: 6; .forEach Loop 3: 8;
                return element * 2      //* is an operator so that you can multiply by the integer. '**' would make it squared. Equivalent of the superscript. If you don't have return then no data is saved.
            })
    
            let filteredNumbers = numbers.filter(function(element) {
                return element > 2
            })
    
            console.log('-------')
            console.log('.forEach Array: ', forEachNumbers)     //returns value as undefined because it's not set to return anything. It's a tool to perform operations in the array, not to perform on the array itself. 
            console.log('.map Array: ', mappedNumbers)      //returns [4, 8, 12, 16];  
            console.log('.filter Array: ', filteredNumbers)     //returns elements greater than 2; returns result [4, 6, 8]
            console.log('Final Array: ', numbers)       //returns Final Array: [2, 4, 6, 8] as there were no changes. 
        

None of the high order array methods affect the original array. They create a new array based on the parameter passed. 'map' loops through the array exactly like how 'forEach' functions and is meant to operate on the element but cannot determine if an element satisfies a certain condition, that's what filter is for.

High order array methods are built into Javascript and are called after the array's been declared.

Array Iteration Practice

            let users =[
                ( id firstName: 'John', lastName: 'Doe', age: 36 ),
                ( id firstName: 'Jane', lastName: 'Doe', age: 24 ),
                ( id firstName: 'Stephen', lastName: 'Lynch', age: 27 ),
                ( id firstName: 'Briar', lastName: 'Rose', age: 14 )
            ]
    
    
            //Using .forEach & .map
    
            function getFirstNames(users){
                let firstNameList = []  //empty array
                users.forEach(function(user){
                    firstNameList.push(user.firstName)
                })
                return firstNameList    //returns array after function runs. [ 'John', 'Jane', 'Stephen', 'Briar']
            }
    
            console.log(getFirstNames(Users))
            
            //which is the same as: 
    
            function getFirstNames(users){
                let firstNameList = users.map(function(user){       //we don't need to declare an empty array container using '.map'
                    return user.firstName       //required for the function to return a result
                })
                return firstNameList    //returns array after function runs. [ 'John', 'Jane', 'Stephen', 'Briar']
            }
    
            console.log(getFirstNames(Users))
    
    
            //More .map Practice
            
            function getFullNames(users){
                return users.map(function(user){
                    return `${user.firstName} $user.lastName`
                })  
            }
    
            console.log(getFullNames(Users)) //returns array[ 'John Doe', 'Jane Doe', 'Stephen Lynch', 'Briar Rose']
    
            //which is the same as: 
    
            console.log(users.map(function(user) {return `${user.firstName} $user.lastName`}))
    
    
            //filter practice
    
            function getAdults(users){
                let adults = users.filter(function () {
                    return adults.age > 18      //when looking for teenages, teens.age >=13 && teens.age <=18
                })
            }
    
            console.log(getAdults(users))
    
    
            //getOldest user
    
            let moreHelp = true; 
    
            function getOldest(users){
                let oldestUser = users[0]       //set location for variable with index value
                users.forEach(function(user){       //set iteration using .forEach
                    if (user.age > oldestUser.age) {        //set condition using if
                        oldestUser = user       //we've set the user to override oldestUser variable every time the loop encounters a user older than the current oldestUser.
                    }
                })
                return oldestUser
            }
    
            console.log(getOldest(users))
    
            //which is the same as this 'sort' function: 
    
            let moreHelp = true; 
    
            function getOldest(users){
                return users.sort(function(user1, user2){       //checks the 2 users in the array and keeps iterating through the array and compares the users. 
                    return user1.age - user2.age    //figures out which of the 2 is greater; there's math going on behind the scene. this is specific to sorting syntax
                })[users.length-1]
            }
    
            console.log(getOldest(users))
        

OOP - Object oriented programming (prototypes & classes)

Object Oriented programminng is a paradigm that is used to structure simple and reusable pieces of code using the concept of classes and objects. The reusable classes are used to create individual instances of objects.

An "object" is a group of related variables and functions where the variables are the properties of an object and the functions are defined as behaviors. So you would have an object that encompasses properties and methods. Properties are the characteristic while methods are the actions that the object can execute.

"Objects are like people. They're living, breathing things that have knowledge inside them about how to do things and have memory inside them so they can remember things. And rather than interacting with them at a very low level, you interact with them at a very high level of abstraction, like we're doing right here. Steve Jobs in 1994: The Rolling Stone Interview

Four fundamental concepts are:

Classes in OOP function more like a collection of objects that the user defines that make the code more manageable. Classes are declared using the 'class' keyword followed by the name of the class. Classes function like a frame or container which objects are built in and can be reused to create more objects.

            class Name{

            }
        

Included in the {} are properties and constructors. Properties can be created multiple ways. They can be declared within the curly braces or they can be included in the constructor.

Constructors are similar to functions where they are able to pass a parameter. They use the 'constructor' keyword and are able to create new objects, use 'this' keyword, and run code then return the new object. If a constructor hasn't been initialized or defined, then a constructor will still be generated by default.

'this' is a function's keyword that refers to the global object. In javascript, the 'this' keyword functions differently compared to other languages and some differences betweet strict and non-strict. Generally in javascript, 'this' is determined by how the function is called, the action is known as runtime binding. The behavior changes when used within an arrow function where they don't include their own 'this' binding. There is a 'bind()' method to set a fixed value of a functions 'this' regardless of how it is called.

            Example from MDN: 
            // In web browsers, the window object is also the global object:
            console.log(this === window); // true
            
            a = 37;
            console.log(window.a); // 37
            
            this.b = "MDN";
            console.log(window.b)  // "MDN"
            console.log(b)         // "MDN"
        

Overall Example:

            class ClassName {
                constructor(parameters) {   //constructor method
                    this.property1 = property1;     //Ex: name
                    this.property2 = property2;     //Ex: gender
                    this.property3 = property3;     //Ex: location
                }
                    behavior() {    //defined method
                        console.log("Action");
                    }

                    getInfo() {     //another method
                        console.log("Property1: " + this.property1 + ", " +
                        "Property2: " + this.property2 + ", " + 
                        "Property3: " + this.property3)
                    }

                    addProperty4(property4) {   //another method; Ex: age
                        return this.property1 + " property4:" + property4;
                    }
                }            

            let newClassName = new ClassName("fitsProperty1", "fitsProperty2", "fitsProperty3");    //creates a new object with properties
            newClassName.behavior();    //invokes defined method that returns 'Action' as the output
            newClassName.getInfo();     //invokes second method that returns: Property1: property1, Property2: property2, Property3: property3 

            let newProperty4 = newClassName.addProperty4('22');     
            console.log(newProperty4);  //returns newClassName property4: 22
        

If a value hasn't been defined when called using 'this' then it will return value as undefined.

Class Inheritance

Inheritence can be described as functionality or features that extends from the parent class and passes those same functions to the children or subgroups.

  • Ex: Object(parent) > Brand > Model
  • Base classes are parents or 'super' classes. They cannot inherit properties or methods of the derived class. Derived classes have properties or methods inherited from the base class as the child or subclass.

                class BaseClass{    //declaring base class
                    //properties
                    //functions/constructors
                }
                
                class DerivedClass extends BaseClass {  //created child class associated with parent
                    //added child properties
                    //added child functions/constructors
                }
            

    Prototypal inheritance - Prior to ES6, this was the ability to access properties from another object. In javascript, this is generally used to add new properties and methods to an existing object constructor where it's essentially told to inherit properties from the prototype or parent. Javascript in particular uses objects named prototype on the backend to implement inheritance.

    After ES6, inheritance was simplified using the'extend' keyword that is used to create a class that is a child of an declared class or expression

    'super' is a keyword that calls functions nexted in an objects parent. Parents are 'super' classes and children are sub-classes. Children of the parent will inherit and get its features from its parent.

                class BaseClass{
                    constructor(parameter1, parameter2) {   //Ex: parameters can be width and height
                        this.parameter1 = parameter1;
                        this.parameter2 = parameter2;
                    }
                }
                class DerivedClass extends BaseClass {
                    constructor(parameter3){    //calls parent's constructor with parameter name
                        super(parameter3, parameter3);   //invokes the parent's functions in the child
                    }
                }
            

    There are key differences between Object oriented programming and procedure oriented programming.

    Promises/Asynchronus Requests

    Promises function like the general use of the term promise. Either the promise is fulfilled or rejected when the result is unable to be completed or has failed. They're similar to callback functions.

                    let p = new Promise((resolve, reject) => {      //2 parameters are passed into the promise. 
                        let a = 1 + 1
                        if (a == 2 ) {
                            resolve('Success')
                        } else {
                            reject('Failed')
                        }
                    })
                

    Asynchronus programming is a form of programming that allows work to run seperately or parallel from the primary application and returns a notification to the main application if the process completed or failed.

    Asynchronus programming is important as it enables your program to continue to be responsive as opposed to waiting for a potentially long running task to finish. Many functions provided by browswers can potentially take a long time and are set as asynchronous.

    For example:

    Asynchronus programming will also help with waiting for pending changes before performing a follow up action in case there is a process that is supposed to happen sequentially.

    While forcing the page to wait, we essentially stop the browser from performing any other processes including viewable changes or responding to events. Asynchronous programming solves this problem by scheduling codes to run in the meantime while waiting for a response or scheduling code to run later.

    Javascript primarily uses callback functions, promises, and 'async'/'await'.

  • Standard .then() to get the data back after making the request and .catch() syntax to catch any possible errors
  • ES6 utilizes promises as a solution instead of callbacks for asynchronous coding. This allows you to make a request for a server and anything that could take a while, you are able to perform other processes on the application without having to wait for a response.

    For Example:

                    function wait(duration){
                        let start = new Date().getTime()
                        let now = start; 
                        while(now < start + duration){
                            now = new Date.getTime()
                        }
                    }
                

    'setTimeout' Functions

    'setTimeout' is a built-in javascript function that waits for the time set in milliseconds before invoking the callback function. The functions that we define can also accept callback functions.

                    setTimeout(() =>{
                        console.log('wait 10 seconds')
                    }, 10000)
                

    Asynchronous functions are able to accept callbacks as parameters. Typically bad practice to have excessive nesting which makes code harder to read.

    For Example:

                    setTimeout(() => {
                        object.firstFunction()
                        setTimeout(() => {
                            object.secondFunction()
                            setTimeout(() => {
                                object.stop()
                            }, 500)     //runs first function and waits 500 milliseconds before next function
                        },500)      //then runs second function and waits 500 milliseconds before next function
                    },500)      //then runs last function after waiting 500 milliseconds
                
    better practice to refactor the code so that it has the time first as a parameter then the arrow functions as a callback:
    //Invoking
                    object.firstFunction(500, () => {
                        object.secondFunction(500, () => {
                            object.firstFunction(500)
                        })
                    })
                
    //Defining
                    function objectAction(time, callback){
                        action = 'name of action'
                        element.src = './url'
                        setTimeout(() =>{
                            stop()
                            callback()
                        }, time)
                    }
                
    callback in this case would be equal to the italics when invoked.

    Promises and '.then'

    Promises are objects that wait for a result to be returned. They were created as a solution to excessive callback function nesting for cleaner code.

    Promise objects support two properties, 'state' and 'result'. While a promise is in the middle of the process, the result is undefined or 'pending.' If the promise is 'fulfilled' then the result is a value, else the 'rejected' result is returned as an error.

    When using a promise as a constructor, the callback function parameter is typically named 'resolve'.

                    function functionName(parameter/objectName){
                        return new Promise(function(resolve) {       //create new promise using the 'new' keyword, pass the new constructor a callback function that accepts a parameter
                            setTimeout(function() {
                                resolve('condition')
                            }, time)
                        })
                    }
                

    '.then' is a method for waiting until a promise has been fulfilled.

                    functionName('object/product name')     
                        .then(function(parameter){  //parameter can be cost or payment required and is based on promise condition
                            //runs based on time when promise was created.
                            console.log(parameter)
                        })
                

    Another example:

                    let p = new Promise((resolve, reject) => {      //2 parameters are passed into the promise. 
                        let a = 1 + 1
                        if (a == 2 ) {
                            resolve('Success')
                        } else {
                            reject('Failed')
                        }
                    })
    
                    //.then will be called when promise resolves successfully
                    p.then((message) => {      //anything inside a .then is going to run for resolve because it will look at the first promise THEN do this after completion.
                        console.log('Then this ' + message)
    
                    //.catch will be called when promise is rejected or fails
                    }).catch((message) = > {    //'.catch' is to catch any errors like the reject states. 
                        console.log('Catch this ' + message)
                    })
                })
                

    Promises are great to use when waiting for images to load or pending data requests to be fulfilled by another server instead so we can define actions for what to do when it has failed. We can choose to either retry it or notify the user of a failure. General Callback Function:

                    const condition1 = false
                    const condition2 = false
    
                    function doingSomethingCallback(callback, errorCallback){   //passed variables as parameters to check and if either of them are true than an error occurs
                        if (condition1) {
                            errorCallback({
                                name: 'First Condition',
                                message: 'This wasn't supposed to happen'
                            })
                        } else if (condition2) {
                            errorCallback({
                                name: 'Second Condition',
                                message: 'Neither was this'
                            })
                        } else {
                            callback('This is fine')
                        }
                    }
    
                    doingSomethingCallback((message) => {
                        console.log('Success: ' + message)      //Neither parameter was true so error wasn't an issue. This message is returned. 
                    }, (error) => {
                        console.log(error.name + ' ' error.message)     //There was an issue. Error name with message. 
                    }
                
    Same callback function using promises instead:
                    const condition1 = false
                    const condition2 = false
    
                    function doingSomethingPromise(){   //parameters aren't needed here and we just need to return a promise instead of a callback
                        return new Promise((resolve, reject) => {
                            if (condition1) {
                                reject({
                                    name: 'First Condition',
                                    message: 'This wasn't supposed to happen'
                                })
                            } else if (condition2) {
                                reject({
                                    name: 'Second Condition',
                                    message: 'Neither was this'
                                })
                            } else {
                                resolve('This is fine')
                            }
                        })
                    }
    
                    doingSomethingPromise().then(message) => {  //No parameters in the promise but you still need () to call it followed by .then to return something
                        console.log('Success: ' + message)      //.then message for success
                    }), .catch(error) => {      //have to close .then ',' before .catch
                        console.log(error.name + ' ' error.message)     //.catch message for error
                    })
                

    Chaining using Methods

    You're able to invoke multiple object methods in a row.

                    let counter = {
                        value: 0
                        increment: function() {
                            counter.value++
                            return counter;
                        }
                    }
    
                    counter
                    .increment()    //calls increment function, value becomes 1
                    .increment()    //value becomes 2
                    .increment()    //value becomes 3
    
                    console.log(counter.value)  //returns 3
                
    in the same way that you're able to chain methods, you're able to chain ''.then'
                    functionName('object')
                        .then( condition => functionName('objectName'))     //runs based on time set when promise was created.
                        .then( condition => console.log(condition))     //runs at the end of the last .then statement based on time set by promise.
    
                

    When using promises to refactor code

                    object.firstFunction(500, () => {
                        object.secondFunction(500, () => {
                            object.thirdFunction(500, () =>{
                                object.fourthFunction(500, () => {
                                    object.firstFunction(500)   //creates a loop from the starting function
                                })
                            })
                        })
                    })
                
    becomes:
                    object.firstFunction(500)
                        .then (() => object.secondFunction(500))
                        .then (() => object.thirdFunction(500))
                        .then (() => object.fourthFunction(500))
                        .then (() => object.firstFunction(500))
                
    if you have .then on multiple lines, syntax REQUIRES you to have the 'return' function otherwise it will not work:
                    object.firstFunction(500)
                        .then (() => {
                            return object.secondFunction(500)
                        })
                        .then (() => 
                        {
                            return object.thirdFunction(500)
                        })
                        .then (() => {
                            return object.fourthFunction(500)
                        })
                        .then (() => {
                            return object.firstFunction(500)
                        })
                

    Async and Await

    New keywords 'async' and 'await' was introduced in ES7 which can handle promises in more of a synchronus function. The newer methods were built using promises and can be used for asynchronous coding.

    Pain points are essentially any specific or recurring problems that the user may experience, such as repetitive coding. Solutions to those various issues that implement new language features are considered 'Syntatic Sugar.' Specifically in computer science where the syntax within a programming language becomes easier to express concisely, read clearly, or provide an alternative way of writing code.

    'async' is a keyword that can be applied before the function keyword and arrow functions. All 'async' functions prioritize waiting for any other functions that return promises manually.

                    async function functionName(parameter){
                        //behavior
                    }
                
    is the same as:
                    function functionName(parameter){
                        return new Promise( resolve => {
                            //behavior
                        })
                    }
                

    'await' is a keyword that can only be used when nested inside an async function before a promise. Await will not allow the function to continue until the promise has been resolved.

                    async function functionName(parameter){
                        await action(time)  //behavior and time in milliseconds inside the parameter
                        return 'condition'
                    }
                
    which is the same as:
                    function functionName(parameter){
                        return new Promise( resolve => {
                            action(time)
                                .then(() => {       //same as: .then(function(condition)(console.log(condition))
                                    resolve('condition')    //which is the same as "console.log(condition)" and "return 'condition'"
                                })
                        })
                    }
                

    Concurrency with Promises

    Concurrency is running multiple processes at the same time using asynchronous logic. 'Concurrency' is implemented by software, whereas 'Parallelism' uses hardware to execute multiple processes at the same time using different CPU Cores.

                    async function functionName(){
                        await condition1()      //pauses code to run this condition
                        await condition2()      //waits for first condition to finish before running
                        await condition3()      //waits for second condition to finish before running
                    }
                
    Each function essentially stops at a checkpoint before proceeding in a long sequence. Each asynchronuous function will run at the same time if 'await' is removed. Concurrency occurs when the functions are being performed at the same time.

    'Promise.all' is a method that accepts promise objects as an array and returns a promise. It's essentially a promise that will wait for the promises in the array to complete.

                    function makeSomething(){
                        let promisesPromises = Promise.all([
                            doSomething1(),
                            doSomething2(),
                            doSomething3()
                        ])
    
                        console.log(promisesPromises)   //passes promise as the parameter
    
                        promisesPromises.then(() => {
                            fulfilledPromise()
                        })
                    }
                
    which is the same as:
                    function makeSomething(){
                        let promisesPromises = Promise.all([
                            doSomething1(),
                            doSomething2(),
                            doSomething3()
                        ]).then(() => {
                            fulfilledPromise()
                        })
                    }
                
    or instead, you can use async/await with Promise.all:
                    function makeSomething(){
                        let results = await Promise.all([   //'let results =' is optional if you don't want to log it on the console
                            doSomething1(),
                            doSomething2(),
                            doSomething3()
                        ])
                        
                        console.log(results)    //will return result of 3 doSomethings
                        fulfilledPromise()  //implied return
                    }
                

    Code snippet starts all processes without waiting for one to finish before starting the next process.

                    const actionOne = new Promise((resolve, reject) => {
                        resolve('Completed first action')
                    })
    
                    const actionTwo = new Promise((resolve, reject) => {
                        resolve('Completed second action')
                    })
    
                    const actionThree = new Promise((resolve, reject) => {
                        resolve('Completed third action')
                    })
    
                    Promise.all([   //array containing the 3 promises. 
                        actionOne,
                        actionTwo,
                        actionThree
                    ]).then((messages) => {     //all the promises should resolve
                        console.log(messages)   //the messages will be returned in an array. If '.race' is used instead of '.all' then the message is returned by the first one completed and the parameter should be 'message' instead as it would be returned in single instance.
                    })  
                

    About DOM - Document Object Model

    'DOM' is an acronym that stands for Document Object Model and is the term used to describe the interaction between HTML and the Javascript interface. The DOM is essentially a representation of HTML as a tree structure seperated by nested tags for children.

    DOM Trees stem from the root 'Document' which is the <html> element and branch off into the <head> and <body> elements. The <head> branch is a parent that contains the title element as a child, and text elements as child of the title. Whereas the <body> element contains more branches based on the independant child elements with a similar relationship structure.

    Nodes

    Nodes are a form of data structure that can be linked to other nodes or data structures while the trees are conceptual structures used to illustrate and depict relationships between nodes/objects.

    Nodes in the DOM are essentially the individual parts of the document which essentially are the relationships or cluster between the parents, child, and siblings. There are twelve node types, but we usually only work with four of them.

    Browsers have preset behaviors to handle specific situations such as;

    DOM - Document Object Model Selection

    Selecting and manipulating elements in the DOM. There are five generally used methods:

    DOM - Document Object Model Manipulation

    Javascript is able to create static and dynamic content by creating and inserting HTML elements to a page.

    Javascript is able to create and edit HTML elements with the 'innerHTML' & 'outerHTML' properties

    innerHTML will select the nested elements within an element

    Source HTML
                    
                
    Javascript
                    let list = document.getElementById("list")
                    console.log(list.innerHTML)
                
    Selects the following: 
                    
  • Object 1
  • Object 2
  • Object 3
  • outerHTML will select the nested elements within an element

    Source HTML
                    
                
    Javascript
                    let list = document.getElementById("list")
                    console.log(list.outerHTML)
                
    Selects the following: 
                    
                

    Appending DOM Elements nests elements with a parent element, they follow specific syntax;

                    parentNode.append(nodes/DOMStrings);
                

    DOM elements is similar to appending and removes the association

                    parentNode.remove(nodes/DOMStrings);
                

    textContent will essentially show the text content contained in the selected element.

                    let text = node.textContent;
                
    Source HTML
                    <div id="footNote">
                    textContent for footnote.
                    <span style="display: none">Hidden Text</span>
                    <!--Commented text-->
                    </div>
                
    Javascript
                    let note = document.getElementById('note');
                    console.log(note.textContent)
                
    Returns the following HTML
                    textContent for footnote.
                    Hidden Text
                
    Still ignores the comments

    .createElement("tag") - is another method used to create an element.

                    let section = document.createElement('section');     //creates new section tag
                    section.id = 'content';  //adds id
                    section.innerHTML '<div>Create div element</div>'; //creates element inside element
                    
                    div.className = 'contentWrapper'    //adds class name
                    section.appendChild(div);    //appends div as a child of the section element
    
                    let h3 = document.createElement('h3');
                    h3.innerHTML = 'Add h3 element to the div';
                    div.appendChild(h3);    //nests h3 title as child of div element
    
                    document.body.appendChild(section)  //if not appended, then not attached to the document. No parents.
                

     Source HTML
                        
                    
                        let navbar = document.querySelector('#navbar');
                        navbar.append('append() Text Link'); 
                        console.log(navbar.textContent);
                    
    HTML returns
                        <ul id='navbar'>append() Text Link<ul>
                    

    .setAttribute is used to set attributes inside HTML element tags.

                    let header = document.createElement('h1')
                    let paragraph = document.createElement('p')
                    header.setAttribute('class', 'textHeaderLg')
                
    Results in the following:
                    <h1 class="textHeaderLg"><<h1>
                    <p></p>
                

  • Learn the Fetch API for making HTTP requests, you can look for a tool for this
  • Events
  • Do not use the 'alert' function as it will stop the rest of your script from running. Just use the console command or run javascript in the console.

  • Basic Form Validation
  • rr-6 import './App.css'; import Button from "react-bootstrap/Button" import Nav from "react-bootstrap/Nav" import Navbar from "react-bootstrap/Navbar" function App() { return (

    Bootstrap Website

    ); } export default App; Password

    Coding Challenge Logic

    Reverse a String

    Challenge; Create a function to reverse a string.

                function reverseString(string) {
                    var final; 
                    for(var i = string.length - 1; i >=0; i--) {    // done in a bit differently to get the descending values as we need to start from the end. loop control has the '-1' is there since javascript index's start at 0 so you need to subtract 1 to get the last index. condition is going down so '>='' for the condition and '--' for the increments.
                        final += string[i];
                    }
                    return final; 
                }
        
                console.log(reverseString('hello'));    //returns olleh
            
                function reverseString(string) {
                    var stringArray = string.split('');
                    var reverseStringArray = string.reverse();
                    var reversedString = reverseStringArray.join('');
                    return reversed string
                }
        
                console.log(reverseString('hello'));    //returns olleh
            
                function reverseString(string) {
                    return string.split('').reverse().join(''); //shorthand using built in methods
                }
        
                console.log(reverseString('hello'));    //returns olleh
            

    Factorialize a Number

    Return the factorial of the provided integer. If the integer is represented with the letter n, a factorial is the product of all ppositive integers less than or equal to n.

    Factorials are the product of an integer and all the integers below it. Often represented with the shorthand notation 'n!'. ie 5! = 1 * 2 * 3 * 4 * 5 = 120

                function factorialize(num) {
                    var result = 1;     // provide variable container
                    for (i = 1; i<=num, i++){  //we have to start the count at '1' since '0' multiplied by anything is 0. We can use num as that's the parameter that is being passed.
                        result = result * i; //same as 'result *= i;''
                    }
                    return result;
                }
        
                factorialize(5);
            

    Palindrome Check

    Given the string, check if it is a palindrome. Palindromes are a string that doesn't changed when reversed (it reads the same backward and forward).

    Note: remove all non-alphanumeric characters(punctuation, spaces, and symbols) and turn everything to lowercase in order to check for palindromes

                function solution(inputString) {
                    const length = inputString.length;
                    const center = length / 2;     //starting point and end point should meet in the center
                  
                    for (let i = 0; i < center; i++) {     
                      if (inputString[i] !== inputString[length - 1 - i]) {        //if start and end do not equal each other 
                        return false;      //return !true value for false
                      }
                    }
                    return true;       //return true value for !false
                  }
            
                function reverseString(inputString) {
                    var final = '';  //required to confirm type = 'string'. 
                    for(var i = inputString.length - 1; i >=0; i--) {    // done in a bit differently to get the descending values as we need to start from the end. loop control has the '-1' is there since javascript index's start at 0 so you need to subtract 1 to get the last index. condition is going down so '>='' for the condition and '--' for the increments.
                    final += inputString[i];
                }
                return final; 
            }
            
                function solution(inputString){
                    if (reverseString(inputString) === inputString)
                    return true;        // can be on the same line as it's only one argument.
                return false;   //do not use } else { in this instance as it will make the values the same and not run through the code.
                }
                
                var inputString = 'eye' //test
                console.log(reverseString(inputString)) //test
                console.log(solution(inputString)); //confirmed result
            

    Regular expressions are expressions that define a specific or match a search pattern.

                function palindrome(string) {
                    var reg = /[\W_]/g    // '/' initiates the regular expression. '[]' is the container, '\W_' stands for non-alphanumeric values, '/g' for global to go through the whole string.
                    var smallString = string.toLowerCase().replace(reg, "");    //removes all non-alphanumeric characters and replaces it with nothing ("").
        
                    var reversed = smallString.split("").reverse().join("");    //splits parameter, reverses string, recombines it.
                    if (reversed === smallString) return true;       // if type & value is equal, return true
        
                    return false;       //else return false
                }
                
                palindrome("racecar");
            

    Mutation Array

    n is a number; a is an array; mutation = changes to the array. Need b to be sum of a[i-1], a[0], a[i+1]. In the case where one of those is not true, then b[0] needs to be 0.

                function solution(n, a) { //n is a number; a is an array; mutation = changes to the array
                var b = []; // array type n.length
                for(i=0; i < n; i++) {
                    if (n==1) {
                        b[0] = a[0]
                    }else if (i==0) {     //condition if index is 0
                        b[0] = a[0] + a[1]   // b first number = a first number + number to right
                    } else if (i==n-1){     //condition for index is at the end
                        b[i] = a[i-1] + a[i]    //b next number + number to left
                    } else {    //conditon for ints being present left and right.
                        b[i] = a[i-1] + a[i] + a[i+1]     //b index plus left right and self
                    
                        }
                        return b
                    }
                }
        
                n = 5
                a = [4, 0, 1, -2, 3]
                console.log(solution(n,a))
            
                function solution(n, a) { //n is a number that represents the array.length; a is an array; mutation = changes to the array
                    for (i=0; i < n; i++) {
                        b[i] = a[i]; // not empty array container, pushes value for 'a' array with same index 
                        
                        if (i-1 >=0) {  // index -1 is greater than or equal to 0
                            b[i] = b[i] + a[i-1];   //then add number to the left
                        }
                        if(i + 1 < n) {   // if index +1 less than length of array
                            b[i] += a[i+1]   //then add number to the right
                        }
                    }
                    return b
                }
        
                n = 5
                a = [4, 0, 1, -2, 3]
                console.log(solution(n,a))
            

    Finding the length of the longest word

    Return the length of the longest word in the provided sentence. Response should be a number.

                function findLongestWord(string) {
                    var words = string.split(" ");   //creates an array of words as a string based on spaces.
                    var longest = 0;  
                  
                    for(i=0; i < words.length; i++) {    //initiates loop
                  
                      if (words[i].length > longest)
                      {  
                        longest = words[i].length;
                      }
                      
                  }
                  
                  return longest;
                  }
        
                  string = 'The quick brown fox jumped over the lazy dog';
                  console.log(findLongestWord(string));
                  console.log(findLongestWord("abc a"));
                  console.log(findLongestWord("a"));
            
                function findLongestWord(string) {
                    var words = string.split(" ");   //creates an array of words as a string based on spaces.
                    var longest ="";    //indicates empty string
                  
                    for (var word of words) {   //of goes over the elements without indexing.
                      if (word.length > longest.length) longest = word;
                      }
                      return longest.length;
                    }
            
                function findLongestWord(string) {
                    return string.split(" ").sort(function(a, b) {return b.length - a.length})[0].length;  //splits the string then sorts it using the sort method. the function makes it sort in descending order and will provide the first index which should be longest word. 
                }
        
                string = 'The quick brown fox jumped over the lazy dog';
                  console.log(findLongestWord(string));
                  console.log(findLongestWord("abc a"));
                  console.log(findLongestWord("a"));
            

    Title Case

    Return the provided string with the first letter of each word capitalized. Make sure the rest of the word is in lower case.

                function titleCase(string) {
                    var words = string.toLowerCase().split(" ");  //converts to lowercase then splits each word seperated by a space.
                  
                    for (i=0; i<words.length; i++) {
                      words[i] = words[i][0].toUpperCase() + words[i].slice(1)  //Sets each word to select first letter and convert it to Uppercase with a method then rejoins it with the rest of the word.
                    }
                  
                    return words.join(" "); //joins array back together as a string with a space in between. 
                  }
                  
                  console.log(titleCase("I'm a little tea pot"))
            
                function titleCase(string) {
                    var titled = string.toLowerCase().split(' ').map(function(elem) {
                      return elem[0].toUpperCase() + elem.slice(1);
                    }) //converts everything to lower case then splits each word seperated by a space. Map method then takes the function then goes through an array and loops through an array of elements and returns the changes specified in the return 
                  
                    return titled.join(" "); //joins array back together as a string with a space in between. 
                  }
                  
                  console.log(titleCase("I'm a little tea pot"))
            

    Largest Numbers in Array

    Return an array consisting of the largest number from each provided sub-array. For simplicity, the provided array will contain exactly 4 sub-arrays.

    Remember, you can iterate through an array with a simple for loop, and access each memember with array syntax arr[i]

    Two dimensional arrays are arrays that are stored within arrays. Note: Expected outcome should be [5, 27, 39, 1001]

                function largestOfFour(array) {
                    var maxArray = [];
                  
                    for (i=0; i < array.length; i++) { //goes through each array
                        var max = array[i][0];  //everytime loop runs, make outter loop = first number in each inner array.
                        for (j=0; j < array[i].length; j++) { // 'j' or 'ii' for nested loops. This will go through each number in the array.
                        var currentElement = array[i][j];
                        if (currentElement >= max) {//Selects through each number to the array. 
                            max = currentElement; //if true then it reassigns nax value to = currentElement. 
                        }
                    }
                    maxArray.push(max); //adds the max number into the set outter array container. This runs until there's no new array indicated by array.length.
                    }
                    return maxArray;  //once inner loop executes, then the stored values are returned.
                }
                
                console.log(largestOfFour([[4, 5, 1, 3], [13, 27 ,18 ,26], [32, 35, 37, 39], [1000, 1001, 857, 1]]))
            
                function largestOfFour(array) {
                    var maxArray = [0, 0, 0, 0];  //predetermine array container with values
                  
                    for (i=0; i < array.length; i++) { //goes through each array
                        for (j=0; j < array[i].length; j++) { // 'j' or 'ii' for nested loops. This will go through each number in the array.
                        var currentElement = array[i][j]; //creates element to go through and select new current index location
                        if (currentElement >= maxArray[i]) {  //Selects through each array. 
                            maxArray[i] = currentElement; //if true then it reassigns max value to = currentElement. 
                        }
                    }    
                }
                return maxArray;  //once inner loop executes, then the stored values are returned.
                }
        
                console.log(largestOfFour([[4, 5, 1, 3], [13, 27 ,18 ,26], [32, 35, 37, 39], [1000, 1001, 857, 1]]))