General Javascript Notes

January 10, 2020

Web Dev

This page is a place for general notes or snippets involving the programming language Javascript.

The remainder operator, sometimes called modulo, returns the number that remains after the right-hand number divides into the left-hand number as many times as it evenly can: 11 % 3 equals 2 because 3 fits into 11 three times, leaving 2 as the remainder.

Every string instance has a property called length that stores the number of characters in that string.

Math

Math.random() will you you a random number between 0 and 1.

Math.floor() takes a decimal number, and rounds down to the nearest whole number.

Using those two methods together, we can generate a random number between 0-50 with the code below:

Math.floor(Math.random() * 50);

Math.ceil() would do the same as Math.floor() except it rounds up to the nearest whole number instead of down. Math.round() will round to the nearest whole number based on the decimal.

Types of variables

let and const are the same as var with some minor differences. let can be changed later on after it is assigned, but const cannot.

When creating a function expression, it is common practice to use const. An example of a function expression is found below.

const calculateArea = function(width, height) {
  const area = width * height;
  return area;
}

When a function (like the above) does not have a name associated with it – ex. myFunction() – then it is called an anonymous function.

An array can be defined with const, and the values can still be changed. The array however cannot be assigned to a different array or a different value type.

Template Literals

Template literals allow your code to be more readable, and also eliminate the need to escape certain characters. The following code will produce an identical result.

console.log('I own a pet ' + myPet);
console.log(`I own a pet ${myPet}.`);

typeof can be used to determine a variable’s type.

const unknown1 = 'foo';
console.log(typeof unknown1); // Output: string

Arrow functions were introduced in ES6. The following two code blocks are identical.

var greeting = function() {
  console.log('Hello World!');  
};
const greeting = () => console.log('Hello World'); 

Short-Circuit Evaluation

The following is a logical operator that checks if a value is assigned to username. If there isn’t one then defaultName will be given the value of Stranger.

let defaultName = username || 'Stranger';

Ternary Operator

Ternary operators are used to simplify an if-else statement. The following two code blocks are identical:

let isNightTime = true;

if (isNightTime) {
  console.log('Turn on the lights!');
} else {
  console.log('Turn off the lights!');
}
isNightTime ? console.log('Turn on the lights!') : console.log('Turn off the lights!');

A switch method is a different way of writing an else-if clause. Here is an example of what a basic one looks like:

let groceryItem = 'papaya';

switch (groceryItem) {
  case 'tomato':
    console.log('Tomatoes are $0.49');
    break;
  case 'lime':
    console.log('Limes are $1.49');
    break;
  case 'papaya':
    console.log('Papayas are $1.29');
    break;
  default:
    console.log('Invalid item');
    break;
}

Functions

With ES6, we can assign default parameters for functions. So, in the following code, we are assigning a default value of stranger to the name parameter. If we run the greeting() function without a parameter, then the default of stranger will be used.

function greeting (name = 'stranger') {
  console.log(`Hello, ${name}!`)
}

greeting('Nick') // Output: Hello, Nick!
greeting() // Output: Hello, stranger!

Arrow functions

Arrow functions are a part of ES6 syntax, and are just a way to not write “function every-time”. The two code snippets below will produce the same result.

const plantNeedsWater = function(day) {}
const plantNeedsWater = (day) => {}

A function body composed of a single-line block does not need curly braces. Also, the result will automatically be returned. This is referred to as implicit return. The example below has one parameter – number.

const sumOfNumbers = number => number + number;

If an anonymous function has more than one, or no parameters, then parentheses are needed. The example below is the same as the above function, except it takes in two parameters – number and otherNumber.

const sumOfNumbers = (number, otherNumber) => number + number;

.push() adds a new item to an array. Example is things.push(‘popcorn’);

.pop() removes the last item from an array

.shift() removes the first item from an array

.slice() grabs a snapshot of items within an array. things.slice(1, 4); will grab the 2nd, 3rd, and 4th items in an array.

.indexOf() tells you what position in the array an item is. Example is things.IndexOf(‘popcorn’);

Loops

Format for a for loop:

for(let i=0; i < things.length; i++) {
   // do something
}

Format for a while loop:

while(age < 23) {
   // do something
}

Format for a do while loop:

do {
   // do something
} while(age < 23)

A do while loop will run once regardless, a plain while loop might not run the first time based on the conditions.

Iterators

.forEach()

const fruits = ['mango', 'papaya', 'pineapple', 'apple'];

fruits.forEach(fruit => console.log('I want to eat a ' + fruit));

.map()

const bigNumbers = [100, 200, 300, 400, 500];
const smallNumbers = bigNumbers.map(num => num/100);

.filter()

const favoriteWords = ['nostalgia', 'hyperbole', 'fervent', 'esoteric', 'serene'];
const longFavoriteWords = favoriteWords.filter(word => word.length > 7);

.filter() and .map() will both return a new array, .forEach() does not

.findIndex()

const animals = ['hippo', 'tiger', 'lion', 'seal', 'cheetah', 'monkey', 'salamander', 'elephant'];
const foundAnimal = animals.findIndex(animal => animal=='elephant');

If there isn’t a single element in the array that satisfies the condition in the callback, then .findIndex() will return -1.

Objects

Keys are strings, but when we have a key that does not have any special characters in it, JavaScript allows us to omit the quotation marks

We must use bracket notation when accessing keys that have numbers, spaces, or special characters in them. Without bracket notation in these situations, our code would throw an error.

let spaceship = {
  'Fuel Type': 'Turbo Fuel',
  'Active Duty': true,
  homePlanet: 'Earth',
  numCrew: 5
};
spaceship['Active Duty'];   // Returns true
spaceship['Fuel Type'];   // Returns  'Turbo Fuel'
spaceship['numCrew'];   // Returns 5
spaceship['!!!!!!!!!!!!!!!'];   // Returns undefined

You can delete a property from an object with the delete operator.

const spaceship = {
  'Fuel Type': 'Turbo Fuel',
  homePlanet: 'Earth',
  mission: 'Explore the universe' 
};

delete spaceship.mission;  // Removes the mission property

When the data stored on an object is a function we call that a method. With the new method syntax introduced in ES6 we can omit the colon and the function keyword. An example is below:

const alienShip = {
  invade () { 
    console.log('Hello! We have come to dominate your planet. Instead of Earth, it shall be called New Xaculon.')
  }
};

For In Loops

The below for…in will iterate through each element of the spaceship.crew object. In each iteration, the variable crewMember is set to one of spaceship.crew‘s keys, enabling us to log a list of crew members’ role and name.

// for...in
for (let crewMember in spaceship.crew) {
  console.log(`${crewMember}: ${spaceship.crew[crewMember].name}`)
};

When accessing properties within a function within an object, you must use this

Certain languages have privacy built-in for objects, but JavaScript does not have this feature. Rather, JavaScript developers follow naming conventions that signal to other developers how to interact with a property. One common convention is to place an underscore _ before the name of a property to mean that the property should not be altered.

const bankAccount = {
_amount: 1000
}

The following is an example of some basic getter and setter methods:

const robot = {
  _model: '1E78V2',
  _energyLevel: 100,
  _numOfSensors: 15,
  get numOfSensors(){
    if(typeof this._numOfSensors === 'number'){
      return this._numOfSensors;
    } else {
      return 'Sensors are currently down.'
    }
  },
  set numOfSensors(num) {
    if(typeof num == 'number' && num >= 0) {
      this._numOfSensors = num;
    } else {
      return 'Pass in a number that is greater than or equal to 0'
    }
  }
};

robot.numOfSensors = 100;
console.log(robot.numOfSensors);

Factory Functions

A factory function is a function that returns an object and can be reused to make multiple object instances.

const monsterFactory = (name, age, energySource, catchPhrase) => {
  return { 
    name,
    age, 
    energySource: energySource,
    scare() {
      console.log(catchPhrase);
    } 
  }
};

You can then call monsterFactory with the necessary arguments and assign the return value to a variable:

const ghost = monsterFactory('Ghouly', 251, 'ectoplasm', 'BOO!');
ghost.scare(); // 'BOO!'

Destructured Assignment

Destructed assignment basically saves you a few keystrokes when if comes to assigning variables out of an object. The following code does the same exact thing:

const residence = vampire.residence; 
const { residence } = vampire; 

Classes

The following is an example of a class. It is identical to the code the following it, which is a basic object.

class Dog {
  constructor(name) {
    this._name = name;
    this._behavior = 0;
  }

  get name() {
    return this._name;
  }
  get behavior() {
    return this._behavior;
  }   

  incrementBehavior() {
    this._behavior ++;
  }
}
let halley = {
  _name: 'Halley',
  _behavior: 0,

  get name() {
    return this._name;
  },

  get behavior() {
    return this._behavior;
  },

  incrementBehavior() {
    this._behavior++;
  }
}

Instances

class Dog {
  constructor(name) {
    this.name = name;
    this.behavior = 0;
  } 
}

const halley = new Dog('Halley'); // Create new Dog instance

The extends keyword makes the methods of one class available inside another class. In the example below the methods inside the Animal class are now available within the Cat class.

class Cat extends Animal {
  constructor(name, usesLitter) {
    super(name);
    this._usesLitter = usesLitter;
  }
}

The super keyword calls the constructor of the parent class. So if you add super(name) to a constructor, when that constructor runs you can use this._name = name; for new instances of the class. (In the above example that would be within the Animal class)

You must always call the super method before you can use the this keyword.

When you append the keyword static in front of a method, that method will only be accessible directly from the class.

You will not be able to use that static method on an instance that you created with the class. So say you ran const leopard = new Animal(‘leopard’); Well, you won’t be able to do lepoard.changeName() if the .changeName() method had static prepended to it.

Using Babel

When installing Babel with npm install babel-preset-env -D the -D will add this package to the dev dependencies in the package.json file

Modules

The following code shows a basic way to create and export a module.

let Menu = {};
Menu.specialty = "Roasted Beet Burger with Mint Sauce";

module.exports = Menu;

To then import a module use the require() function like in the code below:

const Menu = require('./menu.js');

function placeOrder() {
  console.log('My order is: ' + Menu.specialty);
}

placeOrder();

@joekotlan on Twitter