JavaScript

date
Aug 10, 2022
type
KnowledgeBase
year
slug
javascript
status
Published
tags
JavaScript
summary
The essence of everything you need to know about JavaScript (and TypeScript)
TypeScript
TypeScript

Variables

It’s all dynamically typed!
let - variable values const - constant values var - don’t use this anymore, use let instead
👉
If you want to use static typing, look at TypeScript

Functions

function callMe(name) { console.log(name); }
can also be stored in a variable:
const callMe = function(name) { console.log(name); }
could be written as an arrow function:
const callMe = (name) => { console.log(name); }
When it has no arguments, use empty braces
const callMe = () => { console.log("Blah"); }
Return a value
const returnMe = name => { // can omit braces if exactly one argument return name; }
If an arrow function does nothing but returns a value, it can be shortened to:
const returnMe = name => name;

Async Functions

// ASYNC FUNCTION async function callMe(name) { console.log(name); } // ASYNC ARROW FUNCTION const callMe = async (name) => { console.log(name); } await callMe('Markus');

Strings ⌨️

const string1 = "A string primitive"; const string2 = 'Also a string primitive'; const string3 = `Yet another string primitive`; const string4 = new String("A String object");
'cat'.charAt(1) // gives value "a" 'cat'[1] // gives value "a"
Template strings (use backtick `) - allow you to use variables inside ${}
const name = 'Markus'; console.log(`Hello, ${name}`); // prints: Hello, Markus

Equality

1 == 1; // true '1' == 1; // true 0 == false; // true 0 != false; // false
Strict equality
1 === 1; // true '1' === 1; // false 0 === false; // false 0 !== false; // true

Loops and iteration ⚙️

for
for(let i = 0; i < 10; i++) { console.log(i); }
for .. in, for .. of
const arr = [3, 5, 7]; arr.foo = 'hello'; // for .. in - gives you keys for (const i in arr) { console.log(i); // logs: 0, 1, 2, foo } // for .. of - gives you values (but only of iterable objects - notice how it leaves out 'hello'!) for (const i of arr) { console.log(i); // logs: 3, 5, 7 }
Also note that Array has a forEach()!
const fruits = ["apple", "orange", "cherry"]; fruits.forEach((fruit) => console.log(fruit)); // logs: apple, orange, cherry
while
let i = 0; while(i < 10) { console.log(i); i++; }
do while
let i = 0; do { console.log(i); i++; } while(i < 10);
break, continue
let i = 0; while (i < 6) { if (i === 5) break; // exit i = i + 1; if(i === 3) continue; console.log(i); } // output: 1, 2, 4, 5

Modules 📦

To access functionality in another file you need to export it from File A and import it into File B
// FILE A export default const returnMe; //export as default (unnamed) export const someData = 123; //named export export const someFunction = () => { console.log('blah'); }; //FILE B import whatever from './path/to/file.js'; //import default export and give it whatever name you want in the process import { someData, someFunction } from './path/to/file.js'; //import named exports import whatever, { someData } from './path/to/file.js'; //import default and named exports import * as upToYou from './path/to/file.js'; //import all named exports at once console.log(upToYou.someData);

Objects

ℹ️
An object is a collection of properties (a property is an association between a name/key and a value - value can be a function!)
const myCar = new Object(); myCar.make = 'Tesla'; myCar.model = 'Model 3'; myCar.year = 2022;
But usually you’d write this as an object initializer:
const myCar = { make: 'Tesla', model: 'Model 3', year: 2022 };
Unassigned properties of an object are undefined (and not null)
An Object’s properties can contain other Objects, as well as functions:
const myCar = { color: 'red', wheels: 4, engine: { // <-- Object type: 'electric', kW: 336, torque: 639 }, logPower() { // <-- method console.log(this.engine.kW); // Note the use of `this` to refer to the current object } }
Properties can be identifiers, numbers or strings:
const obj = { property1: value1, 2: value2, 'property n': value3 };
Properties can be accessed in different ways:
myCar.model = 'Model Y'; myCar['model'] = 'Cybertruck'; const key = 'model'; myCar[key] = 'Model 2; // anything that converts to a string can be a key!
You can also create objects through a constructor function
function Car(make, model, year) { this.make = make; this.model = model; this.year = year; } const car1 = new Car('Tesla', 'Model 3', 2022); const car2 = new Car('Nissan', 'X-Trail', 2014);
All objects inherit from at least one other object. The object being inherited from is known as the prototype.
 
📘
If you want to learn a lot more about the weirdness of prototypes → read The Joy of JavaScript
You can add properties to previously defined object types through the prototype property.
Car.prototype.color = null; // add color property to all objects of type Car car1.color = 'black'; // assign color black only to the object car1
Object.create() can be useful because it allows you to choose the prototype object for the object you create.
const Animal = { type: 'Invertebrates', // Default value of property displayType() { // Method to display the type of Animal console.log(this.type); } }; const animal1 = Object.create(Animal); animal1.displayType(); // Output: Invertebrates const fish = Object.create(Animal); fish.type = 'Fishes'; fish.displayType(); // Output: Fishes

Duplicating Objects

let nData = { ...data }; // only a shallow copy let nData = structuredClone(data); // deep clone, yeah!

Classes

ℹ️
First and foremost: You don’t really need classes in JS. You can do everything and more with Objects and prototypes.
🤔
Did you know? Classes were introduced to distract you from the craziness that’s going on under the hood (objects + prototypes).
old syntax:
class Person { constructor() { this.name = 'Markus'; } } const person = new Person(); console.log(person.name);
New syntax for defining class properties:
class Person { name = 'Markus; } const person = new Person(); console.log(person.name);
Add functions:
class Person { name = 'Markus'; printName() { console.log(this.name); } } const person = new Person(); person.printName();
or like this (arrow function has the advantage of the this keyword not changing its reference)
class Person { name = 'Markus'; printName = () => { console.log(this.name); } } const person = new Person(); person.printName();
Inheritance
class Human { species = 'human'; } class Person extends Human { name = 'Markus'; printName = () => { console.log(this.name); } } const person = new Person(); person.printName(); console.log(person.species);
Private fields and methods: #
class Person { #name = ''; constructor(name) { this.#name = name; } printName = () => { console.log(this.#name); } } const person = new Person("Markus"); person.printName(); // Markus //console.log(person.#name); // ERROR

Spread and Rest Operator

3 dots:
The spread operator allows you to pull elements out of an array (to split the array into a list of its elements.
const oldArray = [1, 2, 3]; const newArray = [...oldArray, 4, 5]; //this is now [1, 2, 3, 4, 5]
Spread operator used on an object:
const oldObject = { name: 'Cat' }; const newObject = { ...oldObject, age: 3 }; // newObject is now { name: 'Cat', age: 3 }
The rest operator allows us to create variadic functions and place any number of arguments into an array (can be used like params int[] args in C#):
const someObject = { a: 1, b: 2, c: 3, d: 4 }; const { a, b, ...otherAttrs } = someObject; // a, b and rest goes into otherAttrs console.log(otherAttrs); // prints { c: 3, d: 4 }

Destructuring

Allows easy access to values of arrays or objects and assigning them to variables.
const array = [1, 2, 3]; const [a, b] = array; console.log(a); // prints 1 console.log(b); // prints 2 console.log(array); // prints [1, 2, 3]
Destructuring is very useful when working with function arguments:
Watch how we can change this:
const printName = (personObject) => { console.log(personObj.name); } printName({ name: 'Markus', age: 40 }); // prints 'Markus'
into this:
const printName = ({name}) => { console.log(name); } printName({ name: 'Markus', age: 40 }); // prints 'Markus'
we can even add defaults:
const printName = ({name='Billy', age=12}) => { console.log( `${name}, ${age}` ); } printName({ name: 'Markus' }); // prints 'Markus, 12' printName({}); // prints 'Billy, 12' printName(); // ERROR

True and False

ℹ️
Truthy values translate to true when evaluated as a Boolean. A value is truthy if it’s not falsy. (Yep, that is the official definition)
There are only six falsy values:
  • false
  • 0
  • “” (empty string)
  • null
  • Undefined
  • NaN (not a number)

Promises 🙏

The Promise object represents the eventual completion (or failure) of an asynchronous operation and its resulting value.
createAudioFileAsync(audioSettings).then(successCallback, failureCallback);
Promise is in one of these states:
  • pending: initial state, neither fulfilled nor rejected.
  • fulfilled: meaning that the operation was completed successfully.
  • rejected: meaning that the operation failed.
A promise is said to be settled if it is either fulfilled or rejected, but not pending.

Guarantees

Unlike old-fashioned passed-in callbacks, a promise comes with some guarantees:
  • These callbacks will be invoked even if they were added after the success or failure of the asynchronous operation that the promise represents.
  • Multiple callbacks may be added by calling then() several times. They will be invoked one after another, in the order in which they were inserted.

Chaining

Execute two or more asynchronous operations back to back, where each subsequent operation starts when the previous operation succeeds.
doSomething() .then(function (result) { return doSomethingElse(result); }) .then(function (newResult) { return doThirdThing(newResult); }) .then(function (finalResult) { console.log(`Got the final result: ${finalResult}`); }) .catch(failureCallback); //you can leave out error handling until a final .catch()! .finally((info) => console.log("All Done")); //when the original promise is resolved
same thing with arrow functions:
doSomething() .then((result) => doSomethingElse(result)) .then((newResult) => doThirdThing(newResult)) .then((finalResult) => { console.log(`Got the final result: ${finalResult}`); }) .catch(failureCallback); .finally((info) => console.log("All Done"));
To track fallback error handling for promises (or help debug issues with promise management):
process.on("unhandledRejection", (reason, promise) => { /* You might start here by adding code to examine the * "promise" and "reason" values. */ });

Static methods

Promise.all(iterable) - wait for all promises to be fulfilled or for any to be rejected Promise.allSettled(iterable) - wait until all promises have settled (each may fulfill or reject) Promise.any(iterable) - returns as soon as one of them fulfills Promise.race(iterable) - wait until any of the promises is fulfilled or rejected Promise.reject(reason) - returns a new Promise object that is rejected with the given reason Promise.resolve(value) - returns a new Promise object that is resolved with the given value.

Arrays

Arrays are resizable and can contain a mix of different data types.

Create ➕

Array(1, 2, 3) creates a new Array containing [1, 2, 3] Array.from('foo') creates a new Array from an array-like object or iterable object. [”f”, “o”, “o”] Array.of(7) creates a new Array instance with a given number of empty slots const arr = arr1.concat(arr2); - merge 2 or more arrays into a new array entries() returns a new Array Iterator object that contains key/value pairs for each index in the array - link

Stats 📊

Array.isArray(arr) returns true if it’s an array arr.lenth - number of elements in an array

Add and Remove ✂️

pop() - removes the last element and returns it push() - adds one or more elements to the end, returns the new length of the array shift() - remove the first element and return it unshift() - add one or more elements to the beginning of an array and return the new length of the array arr.fill(0, 2, 4) - fill arr with the value 0 from position 2 until position 4. [1, 2, 3, 4] → [1, 2, 0, 0] splice(start, deleteCount, item1, item2, itemN) - changes the contents of an array by removing or replacing existing elements and/or adding new elements in place.

Find, Filter and Sort 🔍

arr.at(2) - gives us the 3rd item in the list, same as arr[2], but here negative values count from the rear forward, so arr.at(-1) gives us the last item in the list (same as arr[arr.length - 1]) arr.every((el) => { el < 40 }) tests whether all elements in the array pass a test implemented by a provided function. arr.filter((el) => { el.length > 6 }) - returns a shallow copy of the array with only the elements that pass the test implemented by the provided function arr.find((el) => el.length > 6) - returns the first element that satisfies the provided testing function arr.findLast() - same as above, but from the back arr.findIndex() and arr.findLastIndex - same as above, but only returns the index. returns -1 if nothing was found. arr.forEach(el => console.log(el)) - execute provided function once for each array element pets.includes('cat') - whether an array includes a certain value arr.indexOf('blah') - returns the first index at which a given element can be found arr.lastIndexOf('blah') - same as above, but from the rear some() - returns true if at least one element in the calling array satisfies the provided testing function sort() - sorts in place according to UTF-16 values ['Monkey', 'Cat', 'Dog'].sort()['Cat', 'Dog', 'Monkey'] - you can also supply a compare Function: sort(function compareFn(a, b) { /* ... */ }) reverse() - reverse the order of the elements

Convert and Process 🔨

map() - creates a new array populated with the results of calling a provided function on every element in the calling array [1, 4, 9, 16].map(x => x * 2) → [2, 8, 18, 32] [0, 1, 2, [3, 4]].flat() - creates a new array with all sub-array elements concatenated into it recursively. → [0, 1, 2, 3, 4] flatMap() - identical to a map() followed by a flat() of depth 1, but slightly more efficient reduce() - executes a user-supplied reducer callback function on each element, passing in the return value from the preceding call. [1, 2, 3, 4].reduce((prev, curr) => prev + curr, 0)10 reduceRight() - same as above, but from the rear arr.copyWithin(target, start, end) - copies part of an array to another location in that same array and returns it values() - returns a new array iterator object that iterates the value of each index in the array slice() - extract a section of the array and return it as a new array ['Fire', 'Air', 'Water'].join('-') - returns a new string by concatenating all elements, separated by commas (default) or a specified separator string. → “Fire-Air-Water”

Leave a comment