Skip to content

Instantly share code, notes, and snippets.

@codeperl
Forked from nuhil/js.md
Created August 25, 2017 12:08
Javascript Handbook

Comments

Single line comments start with //. For multi-line commands, you use /* ... */

// This is a single line comment

/*
 And this is
 a multi-line
 comment
 */

Variables

You can create variables using var, let, const (the last two ones are available only in ES6). Variable names can't start with a number or contain spaces. They can contain letters, numbers, underscores, or $. Variable names are case sensitive.

// This is how you define a variable
// `x` will be `undefined`
var x;

// Declare a constant (the convention is to use CAPS for constants)
const FOO = 42;

// Declare another two variables, using `var` and `let`
var hello = 'world';
let bar = 'baz';

Variables don't have a type. As long as they are not constants, you can change their data:

let foo = 42;
foo = 'bar';
foo
 'bar'

let vs var

let and var are pretty similar, but unlike var, let declares a block scope local variable, optionally initializing it to a value.

let allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. The var keyword which defines a variable to an entire function regardless of block scope.

Let's look at an example:

var a = 42;
if (true) {
  var b = 7;
  let c = 123;
}

// Obviously, we can access the `a` variable
console.log(a);
// => 42

// We can access `b` as well, even it was assigned in the
// if block (see below what happens if the expressions is
// false).
console.log(b);
// => 7

// We cannot access `c` here because it was declared using
// `let`, inside of the `if` block, therefore it's only
// accessible in the `if` block.
console.log(c);
// => Error: c is not defined

Notice how in the first example, we get the final value of i (because we print it after one second). In the other examples (either we manually create a new scope using a function, or use let—which does that for us), the i value inside of the setTimeout (after one second) is the current value of i when the setTimeout was called.

for (var i = 0; i < 7; ++i) {
  setTimeout(function () {
    console.log(i);
    // => 8
    // => 8
    // => 8
    // => 8
    // => 8
    // => 8
    // => 8
    // => 8
  }, 1000);
}

for (let i = 0; i < 7; ++i) {
  setTimeout(function () {
    console.log(i);
    // => 0
    // => 1
    // => 2
    // => 3
    // => 4
    // => 5
    // => 6
    // => 7
  }, 1000);
}

const

const is simple: you can use it for variables which values remain the same.

const PI = 3.14;

PI = 3;
 TypeError: Assignment to constant variable.

Note, this won't freeze the objects:

// Create an object
const myObj = { foo: 'bar' };

// Update the `foo` field
myObj.foo = 42;

// Add a new field
myObj.hello = 'world';

myObj
 { foo: 42, hello: 'world' }

// Tho, if you try to reset the whole thing, you can't
myObj = {};
 TypeError: Assignment to constant variable.

if statemenets

let foo = 42;

if (foo > 40) {
    // do something
} else {
    // do something else
}

Switches

let planet = 'Earth';

switch (planet) {
  case "Mercury":
  case "Venus":
    console.log("Too hot here.");

  case 'Earth' :
    console.log("Welcome home!");
    break;

  case 'Mars' :
    console.log("Welcome to the other home!");
    break;

  case "Jupiter":
  case "Saturn":
  case "Uranus":
  case "Neptune":
  case "Pluto":
    console.log("You may get gold here.");
    break;

  default:
    console.log("Seems you found another planet.");
    break;
}

Primitive values

The following ones, are primitives:

  • Booleans: false, true
  • Numbers: 42, 3.14, 0b11010, 0x16, NaN
  • Strings: 'Earth', "Mars"
  • Special values: undefined, null

Objects

The common way to declare objects is by using the curly braces:

let myObj = { world: "Earth" };

Attention: Objects are compared by reference. That being said, we have this:

let firstObj = {};
let secondObj = {};

// Check if they are equal
firstObj === secondObj
 false

// Comparing an object with itself...
firstObj === firstObj
 true

// Let's point the secondObj to firstObj
secondObj = firstObj

// Now they are equal
firstObj === secondObj
 true

Attention: you have no guarantee that adding the object keys in a specific order will get them in the same order. Object keys are not ordered, even in general JavaScript interpreters which will iterate them in the order of adding them in the object (again, do not rely on this feature).

Arrays

In addition to objects, the array data is ordered by indexes. Arrays are actually objects, having the indexes (numbers from 0 to legnth - 1) as keys.

let fruits = ["apples", "pears", "oranges"];

fruits[1]
 "pears"

Access, add, remove, and update elements

> let fruits = ["Apple"]

// Add to the end of the array
> fruits.push("Pear")
2 // < The new length of the array

 [ 'Apple', 'Pear' ]
 //         ^ This was just added

// Add to the start of the array
> fruits.unshift("Orange")
3 // < The new length of the array

 [ 'Orange', 'Apple', 'Pear' ]
 // ^ This was just added

// Access the element at index 1 (the second element)
> fruits[1]
'Apple'

// How many items do we have?
> fruits.length
3

// Turn the Apple into Lemon
> fruits[1] = "Lemon"
'Lemon'

 [ 'Orange', 'Lemon', 'Pear' ]
 //          ^ This was before an Apple

// Insert at index 1 a new element
> fruits.splice(1, 0, "Grapes")
[] // < Splice is supposed to delete things (see below)
   //   In this case we're deleting 0 elements and
   //   inserting one.

 [ 'Orange', 'Grapes', 'Lemon', 'Pear' ]
 //          ^ This was added.

// Get the Lemon's index
> fruits.indexOf("Lemon")
2

// Delete the Lemon
> fruits.splice(2, 1)
[ 'Lemon' ]

 [ 'Orange', 'Grapes', 'Pear' ]
 //                   ^ Lemon is gone

// Remove the last element
> fruits.pop()
'Pear'

 [ 'Orange', 'Grapes' ]
 //                  ^ Pear is gone

// Remove the first element
> fruits.shift()
'Orange'

   [ 'Grapes' ]
 // ^ Orange is gone

Iterating over Arrays

There are few ways to loop trough an array.

// Using for-loop
var arr = [42, 7, -1]
for (var index = 0; index < arr.length; ++index) {
   var current = arr[index];
   /* Do something with `current` */
}

// Others prefer defining an additional `length` variable:
for (var index = 0, length = arr.length; index < length; ++index) {
   var current = arr[index];
   /* ... */
}

// Another way i using `forEach`:
arr.forEach((current, index, inputArray) => {
   /* Do something with `current` */
});

// Or using the for ... of:
for (let current of arr) {
   /* current will be the current element */
}

Functions

There are a couple of ways to define functions in JavaScript. The common uses are:

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

var sum = function (a, b) {
    return a + b;
}

// Using the ES6 arrow functions
let sum = (a, b) => a + b;

Then you can call the function like:

let result = sum(40, 2);
// => 42

Constructors and Classes

There are a couple of ways you can obtain a class-like functionality in JavaScript.

Using Factory functions
Creating an object and returning it.

function Person (name) {
   // Could be optional
   var self = {};

   // Public field
   self.name = name;

   // Public method
   self.getName = function () {
     // `this` is the `self`
     return this.name;
   };

   return self;
}

var p = Person("Alice");
console.log(p.getName());
// => "Alice"

Using prototypes
By adding a method in the prototype object of a function, you're adding that method as a public method to all the instances of that class.

function Person (name) {
  this.name = name;
}

Person.prototype.getName = function () {
  // `this` is the `self`
  return this.name;
};

var p = new Person("Bob");
console.log(p.getName());
// => "Bob"

Using ES6 classes

class Person {
  constructor (name) {
    this.name = name;
  }
  getName () {
    return this.name;
  }
}

var p = new Person("Carol");
console.log(p.getName());
// => "Bob"

It's also very easy to inherit classes in ES6:

class Musician extends Person {
   constructor (name, instrument) {
     // Call the base class
     super(name);

     this.instrument = instrument;
   }

   play () {
     console.log(`${this.getName()} is playing ${this.instrument}`);
   }
}

var me = new Musician("Johnny B.", "piano");

// Get the name of the musician, who is also a person
console.log(me.getName());
// => "Johnny B."

me.play();
// => "Johnny B. is playing piano."

Async vs Sync

Sometimes you have to wait a little bit for things to be done: such as when making a cake, you have to work on it and you have to wait a while for it to be ready. Most familiar things in our lives are asynchronous.

Sync
Usually, synchronous operations send the response directly, using the return keyword:

// Synchronous sum
function sum (a, b) {
  return a + b;
}
var result = sum(40, 2);
// => 42

Async
To have an async function, you need a source of async stuff. In this example, we will use the setTimeout function. It accepts a function as first argument (which is called callback function) and a number as second argument—representing the time delay after the function is called:

function asyncSum(a, b, adder) {
  console.log("I am working in other stuffs...");
  
  setTimeout(function() {
    let sum = a + b;
    adder(sum);
  }, 5000);
}

asyncSum(10, 10, function(result) {
  console.log(result);
});

What are callbacks?

Callbacks are functions which are sent as an argument to another function and are invoked when something happens.

// An usual factory function
function Cake(type) {
  self.type = type;
  
  self.getName = function() {
    return this.type;  
  }
  
  return self;
}

var busy = false;

// The async function
function makeCake (type, callback) {
  
  if (busy) {
    return callback(new Error("Busy with a cake."), new Cake(type));
  }  
  
  busy = true;
  
  // fake the processing time by using setTimeout
  setTimeout(function() {
    callback(null, new Cake(type));
    busy = false;
  }, 2000);
}

// make use of that async function
makeCake("Apple", function(err, cake) {
  if (err) { console.error(err); }
  console.log("Made an " + cake.getName() + " cake!");
});

// make another use of that async function
makeCake("Peach", function(err, cake) {
  if (err) { console.error(err); }
  console.log("Made a " + cake.getName() + " cake!");
});

Promises

A Promise object represents an operation which has produced or will eventually produce a value. Promises provide a robust way to wrap the (possibly pending) result of asynchronous work, mitigating the problem of deeply nested callbacks (known as "callback hell").

States and control flow
A promise can be in one of three states:

  • pending — The underlying operation has not yet completed, and the promise is pending fulfillment.
  • fulfilled — The operation has finished, and the promise is fulfilled with a value. This is analogous to returning a value from a synchronous function.
  • rejected — An error has occurred during the operation, and the promise is rejected with a reason. This is analogous to throwing an error in a synchronous function.

A promise is said to be settled (or resolved) when it is either fulfilled or rejected. Once a promise is settled, it becomes immutable, and its state cannot change. The then and catch methods of a promise can be used to attach callbacks that execute when it is settled. These callbacks are invoked with the fulfillment value and rejection reason, respectively.

The then and catch methods can be used to attach fulfillment and rejection callbacks:

promise.then(function(value) {
    // Work has completed successfully,
    // promise has been fulfilled with "value"
}).catch(function (reason) {
    // Something went wrong,
    // promise has been rejected with "reason"
});
function sum (a, b) {
   return Promise(function (resolve, reject) {
     // Let's wait a second and only then send the response
     setTimeout(function () {
       if (typeof a !== "number" || typeof b !== "number") {
         return reject(new TypeError("Please provide two numbers to sum."));
       }
       resolve(a + b);
     }, 1000);
   });
}

var myPromise = sum(40, 2);

myPromsise.then(function (result) {
  // After one second we have the response here
  console.log("> Summed 40 + 2: ", result);

  // Let's pass some invalid data and return another promise
  return sum(null, "foo");
}).then(function () {
  // This won't be called because we have an error
}).catch(function (err) {
  // Instead, this `catch` handler is called: (after another second)
  console.error(err);
  // => Please provide two numbers to sum.
});

Create and throw errors

To create an error, you have to use the Error constructor:

let myError = new Error("Something went really wrong.");

// You can even append custom data here
myError.code = "MY_FANCY_ERROR_CODE";

To throw an error, you have to use the throw statement:

throw new Error("Something bad happened.");

There are few types of errors. For example, if you validate the arguments passed to a function, use TypeError:

function sayHello(message) {
  if (typeof message !== "string") {
    throw new TypeError("The message should be a string.");
  }
  console.log(message);
}

Error handling

In general, it is a good practice to validate the data you're passing to function (especially when they are coming from the user input). This way you can avoid TypeErrors to be thrown.

If there's a function which throws an error by design, you can catch it using try - catch:

function assert (truly) {
  if (!truly) {
    throw new Error("Not true.");
  }
}

try {
  // This will *not* throw an error
  assert(42 === 42);

  // This will throw an error, so that will go in the catch
  assert(42 === -1);

  // Everything put after the place where the error was thrown
  // is not executed
} catch (e) {
  console.error(e);
  // => Not true.
}

Note if you have an async function (either callback-based or which returns a promise), you'll do something like this:

// Callback
fetchDataFromServer(function (err, data) {
  if (err) {
    /* do something if you have an error */
  } else {
    /* Do something with `data` */
  }
});
// Promise
fetchDataFromServer().then(function (data) {
    /* Do something with `data` */
}).catch(function (err) {
    /* do something if you have an error */
});

Loops

This will print all the integers from 1 to 42.

for

for (var i = 1; i <= 42; ++i) {
  console.log(i);
}

Using for ... in ... can be used to iterate object keys:

var name = {
  first: "Johnny",
  last: "B."
};

for (var key in name) {
  if (name.hasOwnProperty(key)) {
    console.log(key, name[key]);
    // "first", "Johnny"
    // "last", "B."
  }
}

In ES6 there is a for ... of ... as well. It's pretty neat since it iterates any iterable objects (arrays, strings etc).

let numbers = [-1, 7, 42, 64];
for (let num of numbers) {
  console.log(num);
}
// -1
// 7
// 42
// 64

var country = "Bangladesh";

for(let letter of country) {
  console.log(letter);
}

// B
// a
// n
// g
// l
// a
// d
// e
// s
// h

while

var i = 1;
while (i <= 42) {
    console.log(i);
    ++i;
}

do - while

var i = 0;
do {
    ++i;
    console.log(i);
} while (i < 42);

Strict Mode

The strict mode, when turned on, shows potential errors made by the developer:

a = 42;
// 42

"use strict";
b = 42;
// Error: `b` is not defined

Regular expressions

Regular expressions can be used to match things in strings, such as numbers:

// Get all the numbers from this input (note you'll get an array of strings)
> "Alice was born in 1974, so she's 42 years old in 2016.".match(/[0-9]+/g)
[ '1974', '42', '2016' ]

// Want to get numbers? Map them using the `Number` function
> "Alice was born in 1974, so she's 42 years old in 2016.".match(/[0-9]+/g).map(Number)
[ 1974, 42, 2016 ]

// BE CAREFUL that if there's no match `match` will return `null`
> "Bob is seven years old.".match(/[0-9]+/g)
null

Also, they can be used to replace parts of the strings:

// Mask all the digits of a credit card number, but the last 4
> "1234234534564567".replace(/\d(?=\d{4})/g, "*");
'************4567'

Math functions and constants

// Get the PI number
> Math.PI
3.141592653589793

// Get the E number
> Math.E
2.718281828459045

// Maximum between two numbers
> Math.max(7, 42)
42

// Minimum between numbers (arguments)
> Math.min(7, 42, 255, 264)
7

// Power
> Math.pow(2, 4)
16

// Random number between 0 (inclusive) and 1 (exclusive)
> Math.random()
0.2114640628617317

// Round
> Math.round(41.8)
42

Dates

Use the Date constructor to create date objects.

var now = new Date();
now.getFullYear();
// => 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment