JavaScript Essentials

Author

Spencer Carli

Developer, cat dad, and devout pizza lover. Teaching at React Native School and building apps with Handlebar Labs.

Last Updated: September 18, 2019

This is an introduction and reference guide to JavaScript. This guide is not all encompassing. It exists for people who are already familiar with the basic concepts of programming and want to pick up JavaScript or those who have started learning JavaScript and just want a simple & quick one page reference.

I've put links to further documentation below each topic if you want to dive deeper.

This is a living document. If you have suggestions please let me know!

Misc. Important Things

A few important things that I'll use throughout this guide and you'll see all of the time in JavaScript (JS).

console.log

console.log is the go-to method of debugging anything in JavaScript. It will log whatever you pass to it to the console - which will be the browser console or node console. It will work in whatever environment runs JavaScript.

It accepts any type of argument and as many as you want.

console.log('hello!');
console.log('hello!', 'goodbye!');
console.log([1, 2, 3], { example: true });

Comments

There are two ways to define comments in JavaScript. // will comment out a single line and /* will comment whatever is below it until there is a */.

// this is a single line comment

/*
this is a multi
line
comment
*/

Value Types

String

  • Defined with either ' or "
  • You can typically convert other values to a string by calling .toString() on them.
'hello'; // "hello"
'goodbye'; // "goodbye"

Further Documentation

Number

  • Integers (1) and floats (1.2)
  • parseInt and parseFloat to convert values.
  • NaN represents not a number.
1; // 1
1.2; // 1.2

parseInt('1.2'); // 1
parseFloat('1.2'); // 1.2
parseInt('No'); // NaN

Further Documentation

Boolean

  • True or false, yes or no
  • Basis of all conditional logic
true; // true
false; // false

Further Documentation

Array

  • An ordered list of items.
let foods = [];
foods.push('pizza');
foods.push('tacos');
foods.push('burgers');

foods; // ['pizza', 'tacos', 'burgers'];
foods[0]; // 'pizza'
foods[foods.length - 1]; // burgers
foods.pop(); // burgers
foods; // ['pizza', 'tacos']

Further Documentation

Null

Defined nothingness.

let example = null;
console.log(example); // null

Further Documentation

Undefined

  • Default value for any variables you declare
  • Undefined nothingness
let example;
console.log(example); // undefined

Further Documentation

Object

  • Building block of everything in JavaScript
  • Defined by {}
  • Like a map. Key value pair.
  • Can be nested
  • Can contain any value type
  • JSON is nearly the exact same with some minor differences (no comments allowed)
let info = {
  greeting: 'Hello!',
  age: 100,
  helpful: true,
  favoriteFoods: ['pizza', 'tacos'],
  name: {
    first: 'John',
    last: 'Doe',
  },
  homeTown: undefined,
  favoriteCar: null,
};

info.greeting; // 'Hello!';
info['greeting']; // 'Hello!'
info.name; // { first: 'John', last: 'Doe' }
info.helpful; // true
info.helpful = false;
info.helpful; // false

Further Documentation - Objects

Further Documentation - JSON

Variables

You'll come across three ways to define variables in JavaScript. A variable can be anything - a string, number, function, object, etc. You'll use them all the time, just like in any other programming language.

let

  • Allows you to reassign a variable's value but you cannot redefine a variable.
  • Value type doesn't matter and can change. let x = 'hello' and then x = 3 is valid.
let x = 'hello';
x = 'goodbye'; // VALID
x = 1; // VALID
let x = 'potato'; // NOT VALID

Further Documentation

const

  • Read only value
  • Exception: object and arrays - you can modify them but you can't reassign them
const x = 'asdf';
x = 'qwerty'; // NOT VALID

const y = [];
y.push('hello!'); // VALID

const z = {};
z.hello = true; // VALID

Further Documentation

var

  • "Classic" way to define variables. You'll see it in all older code but not used very often (ever?) anymore.
  • Lawless way of defining variables
  • Scoping can be weird. Use let and const.
var x; // undefined
x = true; // true
var x = 'this works too';

Further Documentation

Operators

Math

// Addition
1 + 1; // 2

// Subtraction
2 - 1; // 1

// Multiplication
3 * 3; // 9

// Division
10 / 2; // 5

// Remainder
6 % 3; // 0
9 % 4; // 1
10 % 4; // 2

Further Documentation

String Concatenation

const firstName = 'John';
const lastName = 'Doe';
firstName + lastName; // "JohnDoe"
firstName + ' ' + lastName; // "John Doe"

See "Template Literals" for a better way (in my opinion) to concatenate strings.

Equality

  • Can be used for any type
  • Be cognizant on more complex types because it might not be checking what you expect
1 === 1; // true
'hello' === 'hello'; // true

1 === 2; // false
'hello' === 'goodbye'; // false

1 !== 1; // false
'hello' !== 'hello'; // false

1 !== 2; // true
'hello' !== 'goodbye'; // true

Further Documentation

Relational Operators

Can be used for different value types but typically only used for numbers

1 > 2; // false
1 < 2; // true
2 >= 2; // true
2 <= 2; // true
3 >= 2; // true
3 <= 2; // false

Further Documentation

Conditional Statements

If/Else

The way you'll typically write conditional code.

let name = 'John';
if (name.length > 3) {
  console.log('hello!');
} else if (name.length >= 0) {
  console.log('keep typing!');
} else {
  console.log('please enter a name');
}

Further Documentation

Switch

Used to easily match values. Make sure to return or break when you get a match so you don't continue to the default response.

let color = 'Orange';

switch (color) {
  case 'Red':
    console.log('go red!');
    break;
  case 'Blue':
    console.log('go blue!');
    break;
  case 'Orange':
    console.log('go orange!');
    break;
  default:
    console.log("sorry, that's not a valid color");
}

Further Documentation

Ternary

A quick way to do an inline decision.

let userInfo = { questionNicely: false };

let question = userInfo.questionNicely
  ? 'What would you like to drink?'
  : 'Whatya want, punk?!';
console.log(question); // Whatya want, punk?!

userInfo.questionNicely = true;
question = userInfo.questionNicely
  ? 'What would you like to drink?'
  : 'Whatya want, punk?!';
console.log(question); // What would you like to drink?

Further Documentation

Loops

For

The basic way to do anything in a loop. Set your initial variable, set a condition that needs to pass to continue to the loop, and an expression to increment your variable.

for (let i = 0; i < 10; i++) {
  console.log(i);
}
/*
0
1
2
3
4
5
6
7
8
9
*/

Further Documentation

While

Another way to do a loop that is a bit more flexible/uses a different syntax.

let i = 0;
while (i < 10) {
  console.log(i);
  i++;
}
/*
0
1
2
3
4
5
6
7
8
9
*/

Further Documentation

Functions

A lot of JavaScript is written following functional programming. Basically a function gets an input, does a calculation, and returns an output. You want to avoid mutating (changing) the input.

There are two ways you'll see functions defined.

Traditional Functions

Traditional functions are defined using the function keyword. They can either be named or anonymous. Typically if you're defining an anonymous function you'll assign it to a variable.

function add(arg1, arg2) {
  return arg1 + arg2;
}

const subtract = function (arg1, arg2) {
  return arg1 - arg2;
};

add(2, 1); // 3
subtract(2, 1); // 1

Further Documentation

Arrow Functions

The new method of defining functions is using arrow notation. I find it to have a more clean syntax and it gives you some more flexibility in how you return values.

You can use implicit returns which mean you can omit the return keyword if you return a value within parenthesis "()" (this is often used in React/React Native) or if the computation all happens on one line.

You can also omit the parenthesis around a function argument if only one exists.

There are also some different ways that arrow functions handle this, but I'll let you read the documentation for more info on that.

const add = (arg1, arg2) => {
  return arg1 + arg2;
};

const subtract = (arg1, arg2) => arg1 - arg2;

const square = (num) => num * num;

add(2, 1); // 3
subtract(2, 1); // 1
square(2); // 4

Further Documentation

Spread/Rest Syntax

This syntax allows us to copy values over easily without having to define each one. It's a great way to make a copy of data. There are other ways to do it but this "syntax sugar" is sweet and used heavily in React/React Native.

Array

const exampleArr = [1, 2, 3];
const secondArr = [...exampleArr, 4];

console.log(exampleArr); // [1, 2, 3]
console.log(secondArr); // [1, 2, 3, 4]

Further Documentation - Spread

Object

const exampleObj = {
  greeting: 'hello',
  farewell: 'goodbye',
  favoriteFood: 'pizza',
};

const person1 = {
  ...exampleObj,
  greeting: 'hi',
};

console.log(person1); //{ greeting: 'hi', farewell: 'goodbye', favoriteFood: 'pizza' }

Function Arguments

const logOnNewLine = (...args) => {
  args.forEach((arg) => {
    console.log(arg);
  });
};

logOnNewLine('hello', 'pizza', 'goodbye');
/*
 hello
 pizza
 goodbye
*/

Further Documentation - Rest

Destructuring

Related but opposite to the spread operator is destructuring. You can do this for objects and arrays. It's an easy way to pull values off of an object/array.

This is used very often in React/React Native.

Object

const exampleObj = {
  greeting: 'hello',
  farewell: 'goodbye',
  favoriteFood: 'pizza',
};

const { greeting, farewell } = exampleObj;
console.log(greeting, farewell); // hello goodbye

Array

const numbers = [1, 2, 3];
const [first, second] = numbers;

console.log(first, second); // 1 2

Template Literals/String Interpolation

Template literals are a great way to easily incorporate a dynamic value into a string. Below you'll see a comparison on two ways to generate a string.

When using template literals you create the string with a "`" and any dynamic values should be wrapped in a ${}.

const firstName = 'James';
const lastName = 'Bond';

const legacyGreeting =
  'The name is ' + lastName + ', ' + firstName + ' ' + lastName;
const greeting = `The name is ${lastName}, ${firstName} ${lastName}`;

console.log(legacyGreeting); // The name is bond, James Bond
console.log(greeting); // The name is bond, James Bond

Further Documentation

Modules

As you write apps you're going to want to split it up among different files to keep your sanity. There are different means to do so but the built in solution in JavaScript is modules.

Export

If you want to share functionality from one file to another you export it. There are two ways to go about this - named and default exports.

For named exports you can either prefix the variable with the export keyword (my preference) or you can do a single export that exports an object of all the variables you want to want export.

To do a default export you just use the export default keywords.

// Name exports
export const myFunction = () => 'hi!';
const myOtherFunction = () => 'goodbye';

export { myFunction, myOtherFunction };

const myDefaultFunction = () => 'potato';

export default myDefaultFunction;

Import

To use exported logic you need to import it from your other file. This is done with the import keyword.

If importing a named export you use curly braces and use the actual name inside of that object. For default functions you import without the curly braces. Named and default exports/imports can be combined.

Note that you can name a default export whatever you want but you need to use the exact name for a named export.

import exportExampleDefault, {
  myFunction,
  myOtherFunction,
} from './exportExample.js';

myFunction(); // hi!
myOtherFunction(); // goodbye
exportExampleDefault(); // potato

Modules are much more extensive than what I covered here. Be sure to read the documentation for this.

Further Documentation

Promises

Promises are a way for us to wait for asynchronous (async) work - that's work that takes some amount of time. For example: an API request is an async request - we need to wait for the server to respond.

There are two ways to work with promises.

This is a pretty integral part of more complex applications written in JS. I highly encourage you to dive into the documentation a bit further.

Promises

The traditional way is to use .then and .catch. Then is used upon success (when a function resolves a value). Catch is used when an error occurs and rejects success.

const myLongRunningFn = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (Math.random() < 0.5) {
        resolve('success!');
      } else {
        reject(new Error('failure!'));
      }
    }, 2000);
  });
};

const doWork = () => {
  myLongRunningFn()
    .then((response) => {
      console.log(response); //success!
    })
    .catch((error) => {
      console.log(error.message); // failure!
    });
};

Further Documentation

Async/Await

There's also some syntactic sugar on top of promises to make it read more synchronously.

You define a function to be async using the async keyword. Once you've done that you can wait for a function to resolve with the await keyword.

It's important that you handle any potential errors that may occur. To do that you want to wrap your code that uses await in a try/catch block. Catch serves the same purpose as it did in the promise chain above.

const doWork = async () => {
  try {
    const response = await myLongRunningFn();
    console.log(response); //success!
  } catch (error) {
    console.log(error.message); // failure
  }
};

Further Documentation


Though this is a lot this just scratches the surface. I think it will get you most of the way there but if you feel I missed something critical please let me know so I can update it!

React Native School Logo

React Native School

Want to further level up as a React Native developer? Join React Native School! You'll get access to all of our classes and our private Slack community.

Join the email list to be notified of all new lessons and classes!