JavaScript Cheat Sheet

You can't get past it - but you don't have to love it either.

#Common Problems

Problems with JavaScript?

Nooooooo way!
Let's get our hands dirty.
Here is the whole articleabout typical problems

Fucked up data types

 11 + 1     // 12
'11' + 1;   // 111
 11 – 1;    // 10
 // magic trick:
'11' — 1    // 10
 // WTF?
JavaScript deals with data types in a very questionable way. What would lead to an error in other languages, does not happen here. Therefore TypeScript is a safe choice.

Unprecise Operations

0.1 + 0.2   // 0.30000000000000004
2.3 * 100   // 229.99999999999997
This is also the case in Python and other languages. So certain arithmetic operations cannot be performed reliably.

Inaccuracy when passing parameters

function add(a, b) {
    return a + b;
}

// one param missing — won’t work:
add(2); // NaN

// one param too much — doesn’t care:
add(2, 2, 10); // 4

Keep the event-loop in mind

let name = ‘Max’

setTimeout(function() {
  name = ‘Tom’
}, 1000)

console.log(name)  // Max
JavaScript does not strictly execute the code from top to bottom and waits - otherwise Tom would be output.

Strange scoping rules

function hello() {
    message = ‘Hello!’
}
console.log(message) // message is not defined

hello()
hello()

console.log(message) // Hello

function hello() {
  message = ‘Hello!’
}
Once a function is executed, the variable is available globally. Works even if the function is called in code before it is even defined (Which is called hoisting).

Weird conditions

!![]            // true
[] == true      // false

!!null          // false
null == false   // false

#Types

Weak Typing - no Type Comparison

'' == '0'     // false
'' == 0       // true
false == '0'  // true
'\t\r\n' == 0 // true
12 == '12'     // true
The double equals sign, means that we want to compare something - but without regard to the data type.

Strict Typing - with Type Comparison

'' === '0'     // false
'' === 0       // false
false === '0'  // false
'\t\r\n' === 0 // false
12 === '12'     // false
The triple equals sign, means that we want to compare something - with regard to the data type.

Essential Types

In JavaScript, there are 7 essential Data Types:
  • strings
  • number
  • boolean
  • object
  • function
  • null
  • undefined
  • Getting the type - typeof()

    typeof undefined  // 'undefined'
    typeof 'Max'      // 'string'
    typeof 2.71       // 'number'
    typeof [1, 2]     // 'object'
    typeof Date.now() // 'number'
    typeof Date.now   // 'function'
    typeof NaN        // 'number'
    

    #Functions

    Regular function

    function greetUser(username) {
        return username
    }
    greetUser('Max') // 'Max
    
    The regular function declaration in JavaScript

    Arrow function

    const greetUser = (username) => {
        return username
    }
    
    Arrow functions are a ES6-way to creating functions. Calling Arrow functions is the same as for regular functions.

    Arrow function shorthands

    const greetUser = username => ( 
        username 
    )
    // or: 
    const greetUser = username => username 
    
    When passing just one parameter or none, you can leave out the '()'. return-statement can be replaced by using the ' => ()' sytnax.

    #Arrays

    In JS, Arrays or Objects. In Vanilla JS, you can add multiple datatypes into one Array.
    The first element of an Array is the index of 0.

    Creating an empty Array

    const people = []
    
    const people = new Array()
    
    Both ways create the same result, but first one is more common.

    Adding to an Array

    let people = ["Max", "Tom"]
    people[2] = "Carl"
    // or:
    people.push("Matt")
    people // [ 'Max', 'Tom', 'Carl', 'Matt' ]
    
    Using the index, you can add an element to any place in the array.
    push adds an element to the end of the array.

    For-Looping through an Array

    let people = ["Max", "Tom", "Carl"]
    
    for(let i = 0; people.length > i; i++) {
        console.log(people[i])
    }
    
    The people.length is 3, since there are 3 elements in it.

    Mapping the Array

    let people = ["Max", "Tom", "Carl"]
    
    people.map(name => console.log(name))
    
    let people = ["Max", "Tom", "Carl"]
    let ages = [21, 25, 32]
    
    const profiles = people.map((name, i) => 
        [name, ages[i]]
    )
    
    // [ [ 'Max', 21 ], [ 'Tom', 25 ], [ 'Carl', 32 ] ]
    
    The first example gives the same output as the for-loop.
    In the example below we use the map function to connect two arrays.

    Joining two Arrays

    let first = [1, 2]
    let second = [3, 4]
    
    first.push(...second)
    
    first // [ 1, 2, 3, 4 ]
    
    In this example we use the spread operator (...) to split the other array. If we didn't do that, but simply pushed the second array, 3 and 4 would both be in one element:
    first: [ 1, 2, [ 3, 4 ] ]

    #Classes

    What is a class?

    Classes belong to the object-oriented philosophy.
    A class is a template to define an object. Using the example of our car class:
    Object type: Car
    Instance: My Lambo - not someone else's. (An instance is always unique)
    Method: drive.

    Simple JS Class

    class Car {
        constructor(speed) {
            this.speed = speed
        }
        drive() {
            console.log("wrooooom")
        }
    }
    
    let lambo = new Car(250) // executed constructor 
    lambo.drive() // wrooooom
    
    The constructor gets executed when we create a new instance.

    Understanding this

    class Car {
        constructor(speed) {}
        drive() {
            console.log(speed) // speed is not defined
        }
    }
    
    class Car {
        constructor(speed) {
            this.speed = speed
        }
        drive() {
            console.log(this.speed) 
        }
    }
    
    Error - we cannot access speed, even though, we passed it into the class.
    With this we can make the variable accessable in the whole class.

    this outside of classes

    console.log(this)   // Window or Global
    console.log(window)  // Window...
    
    setTimeout() // or:
    window.setTimeout() // in Node.js:
    global.setTimeout()
    
    // old-school workaround: duplicating this
    class Car {
        drive() {
            let _this = this
            setTimeout(function() {
                console.log(this)   // window object
                console.log(_this)  // the correct this
            }, 1000)
    } }
    
    // new workaround: using an arrow-function
    class Car {
        drive() {
            setTimeout(() => {
                console.log(this)   // the correct this
            }, 1000)
    } }
    
    In the browser, this refers to the window object, by default. In Node.js, to the global-object.
    When using functions like setTimeout() inside of a class, this inside of setTimeout() will refer to the window.
    For the workaround, see the code below.

    Method problems with this

    class Car {
        constructor(speed) {
            this.speed = speed
        }
        drive() {
            console.log(this.speed)
        }
    }
    
    const lambo = new Car(120)
    lambo.drive()  // 120 - as expected
    
    const driveMethod = lambo.drive 
    driveMethod() // error - this.speed is not defined
    
    Indeed, strange. this is, what is mentioned before the '.drive() - thus is why in the second execution of the function, this gets lost.

    Static methods

    class Car {
        drive() {
          console.log("driving")
        }
    }
      
    const mercedes = new Car()
    mercedes.drive() // driving
    
    // would not work:
    Car.drive()
    
    class Car {
        static drive() {
          console.log("driving")
        }
    }
      
    Car.drive() // driving 
    
    Thanks to the static-keyword, we can make the method accessable outside of the class.

    Extending Classes

    Trucks are a special type of car. If we want to create a special class for them, we can also take the existing properties of cars - and add more. We extend the car class.

    Extending the Car class: Example

    class Car {
        constructor(speed) {
            this.speed = speed
        }
        drive() {
            console.log("wrooooom")
        }
    }
    class Truck extends Car {
        addTrailer() {
            console.log("trailer added")
        }
    }
    
    const UPS_Truck = new Truck(120)
    UPS_Truck.drive()       // from the Car class
    UPS_Truck.addTrailer()  // from the Truck class
    

    Extending: Adding new properties

    class Truck extends Car {
        constructor(speed, trailers) {
            super(speed)
            this.trailers = trailers
        }
        addTrailer() {
            console.log(this.trailers)
        }
    }
    
    const UPS_Truck = new Truck(140, 2)
    UPS_Truck.drive()       
    UPS_Truck.addTrailer()
    
    As you know, when we want to use properties for our class, we need a constructor. But when having in the Truck class another constructor, this would lead to an error - with the super() we can pass everything the Car class needs into it's constructor.
    Important: Even if there is no constructor in the code of the higher class, we still have to call super - then without parameters.

    Extending: Overwriting methods

    class Car {
        drive() {
            console.log("wrooooom")
        }
    }
    class Truck extends Car {
        drive() {
            console.log("the second drive()")
        }
    }
    
    const UPS_Truck = new Truck()
    UPS_Truck.drive()  // the second drive()
    
    When re-creating a function with the same name, the one of the extended class will be used.

    Extending Methods with super()

    class Car {
        drive() {
            return "wrooooom"
        }
    }
    class Truck extends Car {
        drive() {
            return super.drive() + 
            " the second drive()"
        }
    }
    
    const UPS_Truck = new Truck()
    console.log(UPS_Truck.drive()) 
    //wrooooom the second drive()
    
    Return-statements are a best-practise when working with methods. Thanks to the super-object, we can use the methods offered by the higher class (Car).

    #Functional JavaScript

    Intro to Functional JavaScript

    Functional programming follows several principles: No side effects (e.g. changing of memory states by variable). Working with Higher Order Functions and Pure Functions.

    Pure Functions

    // for each x, y will be returned (f(x)=x^2)
    function square(x) {
        return x*x
    }
    square(2) // 4
    square(3) // 9
    
    Like functions in mathematics, Pure Functions return exactly what you expect. They can also get parameters, but usually do not access unpredictable things like Date.now().
    For every same input it returns the same output (deterministic).

    Higher-Order Functions

    function higherOrder(secondFunction) {
        return secondFunction
    }
    
    function f() {
        return "f-function"
    }
    
    higherOrder(f)      // [Function: f]
    higherOrder(f)()    // f-function
    
    A higher-order-function is a function, that receives a functions as a parameter, and returns one.

    Map

    const data = [
        {name: "Max", age: 24},
        {name: "Tom", age: 21},
        {name: "Anna", age: 24},
        {name: "Carl", age: 29}
    ]
    
    const names = data.map((obj) => {
        return obj.name
    })
    
    names // [ 'Max', 'Tom', 'Anna', 'Carl' ]
    
    Map is a high-order function. It passes through every element in the array, and returns the name of every element. This name is then stored in an array. It transforms an array of objects into an array.

    Mapping twice

    // using data from the previous Map example
    const names = data.map((obj) => obj.name).map(
        name => "Person: " + name
    )
    
    names /* [ 'Person: Max', 
    'Person: Tom', 'Person: Anna', 
    'Person: Carl' ] */
    
    Map can be chained. Using the same basis like in the example before, we now can map again, to add something to each element of our resulting array.

    Currying Functions

    const greet = (time, title, lastname) => {
        console.log(
            `Good ${time}, ${title} ${lastname}`
        )
    }
    greet("Morning", "Mr.", "Mozart")
    // Good Morning, Mr. Mozart
    
    const greet = time => 
        title => 
            lastname => 
                `Good ${time}, ${title} ${lastname}`
    
    greet("Morning")("Mr.")("Mozart")
    
    Below you see the same function just curried. By currying the function is partially applied, where the function arguments are passed one after the other and in the meantime are held in a new function, which can be reused arbitrarily.

    #The Window Object

    What is the Window Object?

    window is the top-level object in JavaScript. It represents the opened window of the browser.
    With the this object, you can for example access the local storage, or the URL location.
    Also, document is just a child of the window-object.
    this by default in the browser, always refers to the window object.

    window in Node.js vs. the Browser

    window  // Window { ... }
    this    // Window { ... }
    // in Node.js:
    window  // not defined
    this    // global { ... }
    
    In Node.js, there is obviously no window. Therefore no window-object.
    In the browser but also in Node, this refers to the top-level object, by default.

    Size of the browser

    window.outerWidth 
    window.outerHeight
    // return the dimension of 
    // the browser window itself
    
    window.innerWidth
    window.innerHeight
    // return the dimensions of 
    // the website displayed effectively
    
    In the first example, it does not matter whether the web page is reduced in size by for example, the developer tools.

    State of the website

    document.readyState()
    // returns the current status:
    
    uninitialized — Has not started loading yet
    loading — Is loading
    loaded — Has been loaded
    interactive — Loaded enough; user can interact with it
    complete — Fully loaded

    Get the current URL

    window.location.href 
    // "https://codingcheats.io/javascript"
    
    window.location.hostname 
    // "codingcheats.io"
    
    window.location.pathname 
    // "/javascript" 
    
    Just a few cool examples, there is much more you can get from window.location.

    #Shorthand Syntax ES6

    In JavaScript, especially through ES6, there are some so-called shorthands. They are syntax that replace previous features by making them simpler.

    if-else-shorthand

    if (6 > 5) {
        console.log('6 is greater')
    } else {
        console.log('6 is less than or equal')
    }
    
    console.log(6 > 5 ? '6 is greater' : '6 is less')
    // basic syntax:
    condition ? if true : if false
    

    if-else-shorthand for setting values

    let output = true ? 'true' : 'false'
    output // 'true'
    

    Spread Operator Shorthand

    let numbers = [2, 3]
    let fullNumbers = [1, ...numbers, 4, 5]
    fullNumbers // [1, 2, 3, 4, 5]
    
    We can use the spread operator on iterables like a String or an array and it’ll put the contents of the iterable into individual elements. - Source

    Destructuring

    let people = ['Max', 'Anna', 'Tom']
    let [firstBoy, , secondBoy] = people
    firstBoy // Max
    secondBoy // Tom
    
    This is not a syntax error. If we want to omit an element (Anna) in the array, we simply leave an empty space between the commas.