javaScript - Anton-L-GitHub/Learning Wiki

Original URL: https://github.com/Anton-L-GitHub/Learning/wiki/javaScript

Test

Print

console.log('Hello World');

Variables

let name = 'Frank';  
let age = 55;  
let isFemale = false;  
let favoritAnimal = undefined;  
let selectColor = null; // When we want to clear the value of a variable  

Constants

const num = 1;

Arrays

let colors = ['red', 'blue'];

Array functions

const numbers = [3, 4];  

numbers.push[5, 6]; // adds elements to the end of array  
numbers.unshift[1, 2]; // adds elements to the beginning of array   
numbers.splice[0, 5, 6] // adds element to specific position in array  

Arrow Functions

Find object in an array of objects

const courses = [
    { id: 1, name: 'a' },
    { id: 2, name: 'b' },
];

const course = courses.find(course => course.name === 'b');

console.log(course);

Functions

Example 1:  
function greet(firstName, lastName) {
    console.log('Hello ' + firstName + ' ' + lastName);
}

greet('Peter', 'Pan');  

Example 2:  
function square(number) {
    return number * number;
}

console.log(square(2));

Comparison Operators

let x = 1;
console.log(x === 1); // Equal to
console.log(x !== 1); // Not equal to

=== vs. ==

1 === 1 Strict Equality (Same type and value)
1 == '1' Lose Equality (Same value, doesn't care about the types matching. If they aren't matching the right side will be converted to the same type as the left side)

AND, OR, NOT

AND = &&
OR = ||
NOT = !

Falsy and truthy

Falsy values in JavaScript: undefined, null, 0, false, '', NaN
Anything that is not falsy is truthy

If and switch

If-statements

let role = 'admin';

if (role === 'admin') {
    console.log('Admin');
}
else if (role === 'user') {
    console.log('User')
}
else
    console.log('Unknown')

Switch...case

Compares the value of a variable against other values

let role = 'user';

switch (role) {
    case 'admin':
        console.log('Admin');
        break;
    case 'user':
        console.log('User');
        break;
    default:
        console.log('Unknown');
}

Ternary Operator / Conditional operator

let points = 110;
let type = points > 100 ? 'gold' : 'silver';

If the points are more than 100 you will get 'gold, otherwise 'silver'

Loops

For-loop

for (let i = 0; i < 5; i++) {
    console.log('Hello world')
}

While loop

let i = 0;
while (i <= 5) {
    if (i % 2 !== 0) console.log(i);
    i++;
}

Do-while loop

Always executes at least once, even if the condition evaluates to false.

let i = 0;
do {
    if (i % 2 !== 0) console.log(i);
    i++;
} while (i <= 5);

For-in loop

Used when we ex. want to display all the properties of an object. Can also be used to display all the content in a list.

const person = {
    name: 'Mosh',
    age: 30
};

for (let key in person)
    console.log(key, person[key]);

const colors = ['red', 'green', 'blue'];

for (let index in colors)
    console.log(index, colors[index]);

For-of loop

Used to iterate over the contents of an array.

const colors = ['red', 'green', 'blue'];

for (let color of colors)
    console.log(color);

Iterating an Array with forEach

const numbers = [1, 2, 3];
numbers.forEach(number => console.log(number));

Objects

Object literal

With the object-literal-syntax you create one specific object
Can contain values, methods and other objects
const object - This object can not be reassigned, it is however possible to add and remove properties and methods

const objectLiteral = {
    name: 'Object Objectsson',
    location: {
        address: 'Object Road',
        zip: '12345'
    },
    isJavaScript: true,
    draw: function() {
        console.log('draw');
    }
};

Object Destructuring

Saving the properties of an object as constants
Change the name of the constant like the example bellow

const dog = {
    name: 'rufus',
    breed: 'pudel',
    owner: 'per persson'
}
const { name, breed, owner: ow } = dog;
// Saving the properties of dog as constants, name is the name of the dog, breed is the breed and so on.   
// taking the contents of owner and assigning it to the constant ow   

Factory Functions

Returns an object, no need to use the 'new'-keyword when creating an object
Use if you want to create several objects
camelNotation

function factoryFunction(name, address, city) {
    return {
        name;               
        address;    
        city 
    };    
}

let object1 = factoryFunction('Object Objectsson', 'Object road 1', 'Objectville');

Constructor Function

Constructs/creates objects
Must use the 'new'-keyword to be able to use 'this'
'new' creates an empty object, then it will set 'this' to point to the object and finally it will return the object from our constructor function (so when we call the object.constructor property it will reference our function)
without 'new', 'this' will point to the global object Window()
Use if you want to create several objects
PascalIsUsed

function ConstructorFunction(name, address, city) {
    this.name = name;
    this.address = address;
    this.city = city;
    this.sendMail = function {
         console.log('send');   
    }
}

let object2 = new ConstructorFunction('Object Objectsson', 'Object road 1', 'Objectville');

Constructor Functions vs. Factory Functions

They are equally good
Constructor functions is familiar to developers with previous experience in ex. Java

Classes

New in ES6
Classes in JavaScript are "syntactic sugar" and do not work like classes in ex. Java or C#
They are actually constructor functions

class Animal {
    constructor(type, color) {
        this.type = type;
        this.color = color
    }

    walk() {
        console.log('walk');
    }
}

const ani = new Animal('lion', 'beige');
ani.walk();

Static methods

Methods that are not part of an instance of the class, but the class itself
Utility functions (verktyg) that are not tied to a specific object

class Animal {
    constructor(typeOfAnimal) {
        this.typeOfAnimal = typeOfAnimal;
    }

    walk() {
        console.log('walk');
    }

    static parse(str) {
        const typeOfAnimal = JSON.parse(str).typeOfAnimal;
        return new Animal(typeOfAnimal);
    }

    static makeSound(sound) {
        console.log(`Some animals sound like this: ${sound}`);
    }
}

const myAnimal = Animal.parse('{"typeOfAnimal": "Kangaroo" }');
console.log(myAnimal);

Objects are dynamic

Additional properties and methods can be added and removed after the object has been created

function Dog(breed) {
    this.breed;
}

const myDog = new Dog('pudel');
myDog.name = 'Pelle';             // add new property
delete myDog.breed;               // remove property

Private Properties and Methods

Abstraction = Hide properties and methods in object
Instead of setting something as a propery, we can define it as a local variable. This hides it from the outside.

function Flower(name, color) {
    this.name = name;
    this.color = color;
    let season = 'spring'; // since this is a local variable, it can't be changed from the outside (we can also do this with methods)
}

Private Properties and Methods using Symbols

A Symbol() is a function to generate a unique identifier. We use this unique value as the property name of an object instead of a string.

const _owner = Symbol();
const _trix = Symbol();

class Dog {
    constructor(name, owner) {
        this.name = name;
        this[_owner] = owner;   // private property    
    }

    [_trix]() {
        console.log('Make a secret trick!');    // private method    
    }
}  

const myDog  = new Dog('rufus', 'per persson');

Private Properties and Methods using WeakMaps

A WeakMap is a dictionary, where keys are objects and values can be anything. It's called WeakMaps because the keys are weak. If there are no references to these keys, they will be garbage collected.


const _owner = new WeakMap();
const _jump = new WeakMap();

class Dog {
    constructor(name, breed, owner) {
        this.name = name;
        this.breed = breed;
        _owner.set(this, owner);        // private property // set-method

        _jump.set(this, () => {
            console.log('jump', this);
        });
    }

    getOwner() {
        return _owner.get(this);        // get method
    }

    sitDown() {
        _jump.get(this)();
        console.log('sit');
    }
}

const aDog = new Dog('rufus', 'pudel', 'Peter Persson');
aDog.getOwner();
aDog.sitDown();

Constructor Property

Every object has a property called constructor which references the function that was used to construct or create the object object.constructor

Value vs. Reference types

Value Types

Reference types

Primitives vs. objects

Primitives are copied by their value
Objects are copied by their reference

Primitives example:

let x = 10;
let y = x;

x = 20;

Object example:

let x = { value. 10 };
let y = x;

x.value = 20;

In the objects example, both x and y are pointing to the same location in memory and therefor getting the same value

Enumerating Properties of an Object

Getting access to all the properties and methods of an object

const circle = {
    radius: 1,
    draw() {
        console.log('draw'):
    }
};

Example 1:
for (let key in circle)
    console.log(key, circle[key]);

Example 2:
for (let key of Object.keys(circle))
    console.log(key);

Example 3:
for (let entry of Object.entries(circle))
    console.log(entry);

Check if a given property or method exists in an object
if ('radius' in circle) console.log('yes');

Cloning an Object

const circle = {
    radius: 1,
    draw() {
        console.log('draw');
    }
};

Example 1:
const another = Object.assign({}, circle); // Copies all the properties and functions from circle to the new object

Example 2:
const another = { ...circle }; // The spread operator is cleaner  

{} represents an empty object

Garbage Collection

Finds variables and constants that are no longer used. It deallocate the memory that was allocated to them earlier.
Runs in the background

Math Object

Math.random()
Math.round()
Math.max()
Math.min()

String Object

//String primitive
const message = 'hi';

// String object  
const another = new String('hi');  

Functions
message.length;
message.includes('hi');
message.startsWith('h');
message.endsWith('i');

Code Output
\0 NULL
\' single quote
\" double quote
\\ backslash
\n new line
\r carriage return
\v vertical tab
\t tab

Template Literals

Example 1: 

const message =
`The message starts on this line,
continues on this line
and ends on this line`;

Use `` to write on several lines

Example 2:  

name = 'Emma';

const myMessage =
`Hi ${name}
You look nice today! :)
`

Use ${} to make the message dynamic

How to compare two objects exercise

let address1 = new Address('a', 'b', 'c');
let address2 = new Address('a', 'b', 'c');

console.log(areEqual(address1, address2));
console.log(areSame(address1, address2));

function Address(street, city, zipCode) {
    this.street = street;
    this.city = city;
    this.zipCode = zipCode
}

function areEqual(address1, address2) {
    return address1.street === address2.street && 
        address1.city === address2.city &&
        address1.zipCode === address2.zipCode;
}

function areSame(address1, address2) {
    return address1 === address2;
}

Arrays

Find elements in array (Primitive Types)

Type matters

const numbers = [1, 2, 3, 1, 4];   

numbers.indexOf(1); // returns the index of the given element
number.lastIndexOf(1); // returns the last index of the given element
numbers.includes(1); // returns true if element exists in the array 

Find elements in array (Reference Types)

Call-back function

const courses = [
    { id: 1, name: 'a' },
    { id: 2, name: 'b' }
];

const course = courses.find(function(course) {
    return course.name === 'a';
});

Returns the first element that matches the given criteria, otherwise returns undefined
To get the index, use arrayName.findIndex()

Remove elements in array

const numbers = [1, 2, 3, 4];  

numbers.pop(); // removes last element in array and returns it
numbers.shift(); // removes first element in array and returns it
numbers.splice(startIndex, numOfElementsToRemove) // removes element somewhere in the middle

numbers.length = 0; // empties an entire array

Combine two arrays

Spread Operator
Lets us add the contents of several arrays plus other elements

const first = [1, 2, 3];
const second = [4, 5, 6];

const combined = [...first, 'abc', ...second, 'def];   

Check elements of array

Check if all elements matches our critera with arrayName.every()

const numbers = [1, 2, 3];

const allPositive = numbers.every(function(value) {
    return value >= 0;
});

Check if at least on element in array matches our criteria with arrayName.some()

const numbers = [1, 2, 3];

const atLeastOnePositive = numbers.some(function(value) {
    return value >= 0;
});   

Filter the array with arrayName.filter()

Mapping an array

We can map each item in an array to something else, ex. HTML, strings, objects etc.

const numbers = [1, 2, 3, -4];

const items = numbers
    .filter(n => n >= 0)
    .map(n => ({ value: n }))

Reducing an array

Takes all element in an array into a single value. The value can be a number, a string, an object etc.

const numbers = [1, -1, 2, 3];

const sum = numbers.reduce(
    (accumulator, currentValue) => accumulator + currentValue;
);

Functions

Defining a function

Function Declaration

walk();

function walk() {
    console.log('walk');
}

Function Expression

let run = function <optionalName> () {
    console.log('run');
};

run();

Hoisting

walk();

function walk() {
    console.log('walk');
}

Arguments

Every function has an object called arguments where the keys are the indexes of the arguments
We can use this to iterate through the values

The Rest Operator

Lets us pass a varying number of arguments to a function and puts them in an array
Remember, the rest parameter has to be the last one in function

function sum(...args) {
    console.log(args);
}

sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

Default Parameters

function bank(loan, rate = 3.5, years = 5) {
    return loan * rate / 100 * years
}

This let us either specify the rate and years or use the defaults
Remember to put the parameters with defaults at the end

Getters & Setters

Getters to access properties in objects
Setters to change properties in objects

Getters & Setters in Object Literals

const person = {
    firstname: 'Mosh',
    lastName: 'Hamedani',
    get fullName() {
        return `${person.firstname} ${person.lastName}`
    },
    set fullName(input) {
        const parts = input.split(' ');
        this.firstname = parts[0];
        this.lastName = parts[1];
    }
};
person.fullName = 'John Smith';
console.log(person);

Getters & Setters in Constructor Functions

function Address(street, city, zipCode) {
    this.street = street;
    this.city = city;
    this.zipCode = zipCode;      

    let buildingType = 'apartment';                 // private variable

    Object.defineProperty(this, 'buildingType', {
        get: function() {
            return buildingType;
        },
        set: function(value) {
            if (typeof(value) === 'string')
                buildingType = value;
        } 
    });
};

let myAddress = new Address('a', 'b', 12345);

console.log(myAddress.buildingType);                // get buildingType
myAddress.buildingType = 'house';                   // set buildingType

Getters and Setters in Classes

const _owner = new WeakMap();                       // private property 

class Dog {
    constructor(name, breed, owner) {
        this.name = name;
        this.breed = breed;
        _owner.set(this, owner);       
    }

    get getOwner() {                                // Getter 
        return _owner.get(this);        
    }

    set setOwner(value) {                           // Setter
        if (typeof(value) === 'string')
            _owner.set(this, value);
    }
}

const aDog = new Dog('rufus', 'pudel', 'Peter Persson');
console.log(aDog.getOwner);
aDog.setOwner = 'Anna Andersson';

Try and Catch

const person = {
    firstname: 'Mosh',
    lastName: 'Hamedani',
    set fullName(input) {

        if (typeof input !== 'string') 
            throw new Error('Input is not a string'); // thows an exception

        const parts = input.split(' ');
        if (parts.length !== 2)
            throw new Error('Enter a first and last name');
        
        this.firstname = parts[0];
        this.lastName = parts[1];
    }
};

try {
    person.fullName = '';
}
catch (e) {
    console.log(e);
}

console.log(person);

Let vs. Var

OOP

  1. Encapsulation
    • Groups related variables and functions together so we can reduce complexity and increase reusability
  2. Abstraction
    • Complexity is hidden, only shows the essentials. Reduces complexity and isolates the impact of changes
  3. Inheritance
    • Eliminates redundant code
  4. Polymorphism
    • Refactor ugly switch/case statements

Inheritance

Enables an object to take on properties and methods of another object
Classical vs. Prototypical Inheritance

Multilevel Inheritance

Example of inheritance

Prototypes & How to inherit from another object & Super Constructors

A prototype is like a parent of another object. An object inherits from the prototype.
We have a method for creating an object with a given prototype:

function Animal(sound, color) {
    this.sound = sound;
    this.color = color;
}

function Dog(breed, sound, color) {
    Animal.call(this, sound, color); // this is how you call the SUPER CONSTRUCTOR
    this.breed = breed;
}

function Cat(food, sound, color) {
    Animal.call(this, sound, color)
    this.food = food;
}

// Intermediate Function Inheritance 
function extend(Child, Parent) {
    Child.prototype = Object.create(Parent.prototype);  // returns an object that inherits from the parent
    
    Child.prototype.constructor = Child;  // when changing the prototype of an object, you should also reset the constructor (otherwise we can't create ex. the dog-objects based on it's constructor, we will get an animal-object instead)
}

extend(Dog, Animal);
extend(Cat, Animal);


let myDog = new Dog('pudel', 'woof', 'white');
let myCat = new Cat('meat', 'mjauu', 'black');

console.log(myDog);
console.log(myCat);

Inheritance in Classes

Easy! Use extends

class Plant {
    constructor(typeOfPlant) {
        this.typeOfPlant = typeOfPlant;
    }

    grow() {
        console.log('grow');
    }
}

class SunFlower extends Plant {                         // extends
    constructor(color, season, typeOfPlant) {
        super(typeOfPlant);                             // super
        this.color = color;
        this.season = season;
    }

    bloom() {
        console.log('bloom');
    }
}

const myGarden = new SunFlower('yellow', 'summer', 'flower');

Method Overriding

Override a method that is defined in the parent
We do this by redefining the method in the child-object

function extend(Child, Parent) {
    Child.prototype = Object.create(Parent.prototype);
    Child.prototype.constructor = Child;
}

function Animal() {
}

Animal.prototype.duplicate = function() {
    console.log('duplicate');
}

function Dog() {
}

extend(Dog, Animal);


// must place this AFTER we extend it
Dog.prototype.duplicate = function() {
    console.log('duplicate dog');
}

let myDog = new Dog();

Method Overriding in Classes

class Plant {
    constructor(typeOfPlant) {
        this.typeOfPlant = typeOfPlant;
    }

    grow() {
        return 'grow';
    }
}

class SunFlower extends Plant {
    constructor(color, season, typeOfPlant) {
        super(typeOfPlant);
        super.grow();

        this.color = color;
        this.season = season;
    }

    grow() {
        super.grow();                       // super
        return 'sunflower grow';            // Overriding
    }
}

const myGarden = new SunFlower('yellow', 'summer', 'flower');
console.log(myGarden.grow());

Polymorphism

Provides a way to call the same method (from a parent-object) on different child-objects and also changing it depending on the child-object.
The Dog and Cat objects will provide different implementations of a method in Animal, this is called "polymorphism"

"Use Strict"

use strict is set at the beginning of a script or function to indicate that the code should be executed in strict mode
In strict mode you can not use undeclared variables, if mistyping a variable name you will get an error and not a new variable, etc.
Changes some silent errors to throw errors, fixes mistakes that make it difficult for JS engines to perform optimizations (strict mode code can sometimes be made to run faster than identical code that's not strict mode), it also prohibits some syntax likely to be defined in future versions.
Strict mode for entire scripts:

'use strict'
let message = 'Hi! I'm a strict mode script!';

Strict mode for functions

function strict() {
    'use strict';
    return 'I'm a strict function'
}

Strict mode for modules

function strict() {
    // because this is a module, I'm strict by default
}
export default strict;   

Modules

Programs are divided into modules, just like books are divided into chapters.

CommonJSModules

Cohesion = Things that are highly related go together
File cat.js:

const _name = new WeakMap();

class Cat {
    constructor(name) {
        _name.set(this, name);
    }

    getName() {
        console.log(`The cats name is ${_name.get(this)}`)
    }
}

module.exports = Cat;                   // export cat-module

File index.js

const Cat = require('./cat');           // require() to import the cat-module

const myCat = new Cat('misse');
myCat.getName();

ES6 Modules

File cat.js:


const _name = new WeakMap();

export class Cat {                  // Cat will be private if we don't export it (WeakMap will still be private even if we export Cat)
    constructor(name) {
        _name.set(this, name);
    }

    getName() {
        console.log(`The cats name is ${_name.get(this)}`)
    }
}

File index.js:

import {Cat} from './cat.js';

const myCat = new Cat('misse');
myCat.getName();

ES6 Tooling

Only needed when building browser applications
Transpiler

Bundler