Last modified: October 12, 2024

This article is written in: 🇺🇸

What is JavaScript?

JavaScript is a programming language that is primarily used for client-side scripting (making web pages interactive). Since NodeJS we can also use JavaScript in server-side scripting (e.g. for APIs).

Main idea:

Skills Every JavaScript Developer Should Have

  1. A strong understanding of basic syntax and concepts is necessary, including variables, data types, operators, conditionals, and loops, as they form the foundation of JavaScript programming.
  2. Familiarity with functions and scope is essential, as functions allow for code reuse, and understanding scope ensures that variables are used correctly within different contexts.
  3. Knowledge of asynchronous programming techniques, including callbacks, promises, and async/await, is crucial for handling operations like API requests and other time-consuming tasks without blocking the main thread.
  4. DOM manipulation skills are vital for creating interactive web pages, enabling developers to add, remove, and modify HTML elements dynamically in response to user actions.
  5. The ability to work with APIs and JSON is essential, as it allows JavaScript developers to fetch data from external sources, such as RESTful APIs, and integrate it into web applications.
  6. Debugging and testing are critical skills for identifying and resolving issues in JavaScript code. Familiarity with browser developer tools and debugging methods improves development efficiency.
  7. Regular use of resources like MDN (Mozilla Developer Network) is recommended for up-to-date documentation, learning new JavaScript features, and staying informed about best practices.

Fundamentals

The following are the fundamental concepts of JavaScript:

Adding JavaScript to the HTML

You can either inline JavaScript or include refrence to an external JavaScript file:

  1. Inline JavaScript is put between <script> tags:

<script>
  // JavaScript code goes here
</script>

  1. External JavaScript file is set in the src attribute of the <script> tag:

<script crossorigin="anonymous" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>

Null and Undefined

  1. Undefined means that a variable has not been assigned a value.
  2. Null is a value set to a variable that is supposed to represent the absence of a value.

var x;
console.log(x); // undefined

var y = null;
console.log(y); // null

console.log(typeof x); // undefined
console.log(typeof y); // object

console.log(x === y); // false
console.log(x == y); // true

Useful Built-In Methods

A few useful built-in methods that you can use in JavaScript:

  1. console.log() - to display messages in the console
  2. alert() - to display a message in an alert box
  3. prompt() - to get input from the user
  4. confirm() - to ask the user a question and get a yes or no answer
  5. parseInt() - to convert a string to an integer
  6. parseFloat() - to convert a string to a floating point number
  7. isNaN() - to check if a value is not a number
  8. isFinite() - to check if a value is a finite number
  9. Number() - to convert a string to a number
  10. String() - to convert a number to a string
  11. Boolean() - to convert a value to a boolean
  12. Array() - to convert a value to an array
  13. Object() - to convert a value to an object
  14. Date() - to get the current date and time

Let's take a look at some examples:

var name = prompt("Enter your name");
alert("Hello " + name);

Numbers

Some of the most common number operations:

  1. number.toFixed(n) - returns a string with n decimal places for a variable named number
  2. number.toPrecision(n) - returns a string with n significant digits for a variable named number
  3. number.valueOf() - returns the number as a primitive value
  4. parseInt(string) - returns the first number in the string
  5. parseFloat(string) - returns the first floating point number in the string
  6. Number.MAX_VALUE - largest possible JS number
  7. Number.MIN_VALUE - smallest possible JS number
  8. Number.NEGATIVE_INFINITY - -Infinity
  9. Number.POSITIVE_INFINITY - Infinity

Let's parse a floating point number from a string and display it with two decimal places:

var pi = parseFloat("3.14159");
console.log(pi.toFixed(2));

Common Math Operations

Some of the most common math functions:

In the example below we use the Math.random() function to generate a random number between 0 and 1 and then display the value of sine function at that point:

var x = Math.random();
var y = Math.sin(x);
console.log(y);

Comparison Operators

The comparison operators are used to compare two values.

Operator Description
== Equal to
=== Strictly equal to
!= Not equal to
!== Strictly not equal to
< Less than
> Greater than
<= Less than or equal to
>= Greater than or equal to

In the example below we compare two numbers:

var x = 10;
var y = 20;

console.log(x == y); // false
console.log(x < y); // true

Logical Operators

The logical operators are used to combine two or more conditions.

Operator Description
&& Logical AND
&#124;&#124; Logical OR
! Logical NOT

In the example below we use logical operators to check if a number is greater than 10 and at the same time less than 20:

var x = 15;
var y = 20;

console.log(x > 10 && x < 20); // true
console.log(y > 10 && y < 20); // false

Conditionals

The conditionals are used to execute different code depending on the value of a variable.

Operator Description
if Execute code if a condition is true
else Execute code if a condition is false
else if Execute code if a condition is false and another condition is true

In the example below we use conditionals to check if a number is greater than 10 and at the same time less than 20:

var x = prompt("Enter a number");

if (x > 10 && x < 20) {
  console.log("The number is between 10 and 20");
} else {
  console.log("The number is not between 10 and 20");
}

While Loops

The while loops are used to execute a block of code as long as a condition is true.

Operator Description
while Execute code as long as a condition is true

In the example below we use a while loop to count from 1 to 10:

var i = 1;

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

For Loops

The for loops are used to execute a block of code a number of times.

Operator Description
for Execute code a number of times

In the example below we use a for loop to count from 1 to 10:

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

Functions

A function is a named block of code that performs a specific task. We already used built-in functions like alert() and prompt() to display messages and get input from the user. Each function has to be first defined and then called. Once defined, the function can be called as many times as needed.

In the example below we create a function that calls the console.log() two times:

// Function definition
function sayHello() {
  console.log("Hello");
  console.log("World");
}

sayHello(); // Function call

Function Arguments

The function arguments are the values that are passed to the function when it is called.

In the example below we create a function that takes two arguments and adds them together:

// Function definition
function add(x, y) {
  console.log(x + y);
}

// Function call
add(10, 20); // 30

The "return" Keyword

The "return" keyword is used to return a value from a function.

In the example below we create a function that takes two arguments and adds them together:

// Function definition
function add(x, y) {
  return x + y;
}

// Function call
var result = add(10, 20);
console.log(result); // 30

ES6 Arrow Functions

Arrow functions are a new way to define functions in JavaScript. They are a shorter syntax for writing function definitions.

In the example below we create a function that takes two arguments and adds them together:

// ES5
function add(x, y) {
  return x + y;
}

// ES6
const add = (x, y) => {
  return x + y;
}

Scope

The scope of a variable is the part of a program where that variable can be accessed.

Variable Type Scope Mutability Hoisting Description Best Practices
var Global or function Mutable Hoisted but initialized as undefined - var is function-scoped, meaning it’s accessible throughout the function where it’s declared.
- Variables declared with var are hoisted to the top of their scope, meaning they are accessible before their declaration (with an undefined value).
- Can be redeclared within the same scope.
Avoid using var due to potential issues with scope and hoisting. Instead, use let or const.
let Block Mutable Hoisted but not initialized - let is block-scoped, meaning it’s only accessible within the block (e.g., inside a loop or conditional statement) where it’s declared.
- While let variables are hoisted, they are not initialized, so referencing them before declaration results in a ReferenceError.
- Can’t be redeclared in the same scope.
Use let when you expect the variable value to change later in the code.
const Block Immutable (value cannot be reassigned) Hoisted but not initialized - const is also block-scoped and follows the same scoping and hoisting rules as let.
- Values assigned to const cannot be reassigned. However, if the value is an object or array, its properties or elements can still be modified.
- Can’t be redeclared in the same scope.
Use const by default when you don’t plan to reassign the variable, as it provides more predictable behavior.

In the example below we create a variable that is accessible from anywhere in the program:

var x = 10;

function add(y) {
  return x + y;
}

console.log(add(20)); // 30

In the example below we create a variable that is accessible only from within the block:

var x = 10;

{
  var a = 20;
  let b = 15;
  console.log(a + b); // 35
}

function add(y) {
  return x + y;
}

console.log(add(a)); // 30
console.log(add(b)); // Uncaught ReferenceError: y is not defined

Higher-Order Functions

Higher-order functions are functions that take other functions as arguments or return functions.

In the example below we create a function that takes another function as an argument:

function add(x, y) {
  return x + y;
}

function multiply(x, y) {
  return x * y;
}

function doMath(x, y, callback) {
  return callback(x, y);
}

console.log(doMath(2, 3, add)); // 5
console.log(doMath(2, 3, multiply)); // 6

Arrays

Arrays are used to hold several values under a single name and to organize them using indexes represented by consecutive integers.

Let's create an array of numbers:

var numbers = [1, 2, 3, 4, 5];
console.log(numbers); // [1, 2, 3, 4, 5]

Let's let the user enter a number and add it to the array:

var numbers = [];

for (var i = 0; i < 5; i++) {
  var number = prompt("Enter a number");
  numbers.push(number);
}

console.log(numbers);

Copying Arrays

The array can be copied using the .slice() method:

var numbers = [1, 2, 3, 4, 5];
var numbersCopy = numbers.slice();

console.log(numbers); // [1, 2, 3, 4, 5]
console.log(numbersCopy); // [1, 2, 3, 4, 5]

To copy only a part of the array, use the .slice() method with two arguments:

var numbers = [1, 2, 3, 4, 5];
console.log(numbers.slice(1, 3)); // [2, 3]

Mutators

The array can be modified using the .push() and .pop() methods:

var numbers = [1, 2, 3, 4, 5];

numbers.push(6);
console.log(numbers); // [1, 2, 3, 4, 5, 6]

numbers.pop();
console.log(numbers); // [1, 2, 3, 4, 5]

Accessors

Methods that return a new value or representation are known as accessor methods.

  1. .join() - Joins all elements of an array into a string.
  2. .reverse() - Reverses the order of the elements in an array.
  3. .sort() - Sorts the elements of an array.
  4. .concat() - Combines two or more arrays.
  5. .slice() - Extracts a part of an array.
  6. .indexOf() - Searches an array for an element.
  7. .lastIndexOf() - Searches an array for an element from the end.

In the example below we first use concat() to combine two arrays, then we sort the result and finally we call the join() method to join the elements of the array into a string:

var numbersA = [5, 6, 2, 1, 8];
var numbersB = [9, 7, 1, 10, 4];

var numbers = numbersA.concat(numbersB);
numbers.sort();

console.log(numbers.join()); // 1,1,2,4,5,6,7,8,9,10

Array Methods: Iterators

The array can be iterated using the .forEach() method:

var numbers = [1, 2, 3, 4, 5];

numbers.forEach(function(number) {
  console.log(number);
});

Strings

Strings are sequences of characters. They are used to represent text. We use single or double quotes to create strings.

An example of a string is:

var name = "John";
console.log(name); // John

Common String Methods

Some of common string methods include:

  1. .indexOf() - Searches a string for a specified value and returns the position of the match.
  2. .lastIndexOf() - Searches a string for a specified value and returns the position of the match.
  3. .slice() - Extracts a part of a string and returns the extracted part in a new string.
  4. .replace() - Finds a match between a regular expression and a specified string, and returns a new string with the matches replaced.
  5. .toUpperCase() - Converts a string to upper case.
  6. .toLowerCase() - Converts a string to lower case.
  7. .concat() - Combines two or more strings.
  8. .charAt() - Returns the character at the specified index (position) of a string.
  9. .charCodeAt() - Returns the Unicode of the character at the specified index (position) of a string.

Lets slice the string "John loves JavaScript" from index 5 to index 10:

var text = "John loves JavaScript";
console.log(text.slice(5, 10)); // loves

Classes

Classes are a way to capture under a single name a set of related properties (data) and methods (functions). The class is a blueprint for creating objects.

Lets create a class that represents a person:

// Class definition
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  speak() {
    console.log(Hello, my name is ${this.name} and I am ${this.age} years old.);
  }
}

var john = new Person("John", 30); // an object john is created
var jane = new Person("Jane", 25); // an object jane is created

john.speak(); // Hello, my name is John and I am 30 years old.
jane.speak(); // Hello, my name is Jane and I am 25 years old.

Arrays vs Objects

Lets create an array and object containing the same data:

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
}

var point = new Point(5, 8);
var array = [5, 8];

console.log(point.x, point.y); // 5, 8
console.log(array); // [5, 8]

Exceptions

Throwing Exceptions

  1. throw - Throws an exception.

throw new Error("An error has occurred.");

Try/Catch Blocks

The following syntax is used to handle exceptions:

  1. try - The try block contains the code that might throw an exception.
  2. catch - The catch block contains the code that executes when an exception occurs.
  3. finally - The finally block contains the code that executes regardless of whether or not an exception occurred.

try {
  // code that might throw an exception
} catch (e) {
  // code that executes when an exception occurs
} finally {
  // code that executes regardless of whether or not an exception occurred
}

Types of Errors

  1. ReferenceError - Thrown when a variable or function is not defined.
  2. TypeError - Thrown when a value is not of the expected type.
  3. SyntaxError - Thrown when a syntax error is encountered.
  4. URIError - Thrown when an invalid URI is encountered.

Dom

The DOM is a programming interface that allows you to access and manipulate the content of the web page.

Let's look at the following HTML code:

<html>
<head>
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>

In the example above:

Now let us modify some properties of the <h1> tag using JavaScript:

var h1 = document.querySelector("h1");
h1.style.color = "red";
h1.style.fontSize = "50px";
h1.style.textAlign = "center";

DOM Element Selector Methods

The following methods can be used to select elements from the DOM:

Here is an example of how to use the .getElementById() method to change the background color to a gradient from light blue to dark blue.

var div = document.getElementById("container");
div.style.background = "linear-gradient(to right, #00ffff, #0000ff)";

Edit DOM Elements

Once selected, you can edit the content of the element using the following methods:

Let's append some text to a paragraph with id paragraph:

var paragraph = document.getElementById("paragraph");
paragraph.innerHTML += "This text was appended using JavaScript.";

DOM Events

There are two types of events:

Let's add an event listener to the button with id button:

var button = document.getElementById("button");
button.addEventListener("click", function() {
  alert("The button was clicked!");
});

ES6+ Features

ES6+ features are JavaScript features that were added to the language in 2015. Those futures are widely considered to be a great improvement on the language.

Spread operator

Let's take a look at a simple example:

var numbers = [1, 2, 3, 4, 5];

// Spread operator
var newNumbers = [...numbers, 6, 7, 8, 9, 10];

// Output
console.log(newNumbers); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Destructuring

Destructuring is a JavaScript feature that allows you to extract data from arrays and objects into distinct variables.

Let's take a look at a simple example:

var numbers = [1, 2, 3, 4, 5];
var [first, second, third] = numbers;

// Output
console.log(first); // 1
console.log(second); // 2
console.log(third); // 3

Promises and Async/Await

Let's take a look at aexample:

async function getData() { // async function declaration
  var response = await fetch("https://jsonplaceholder.typicode.com/users"); // awaitings the response of the fetch call
  var data = await response.json(); // awaitings the response of the json call
  console.log(data);
}

Template strings

Template strings are a new type of string literal that allows embedded expressions.

In the example below we will use two variables in a template string:

var name = "John";
var age = 30;
var sentence = My name is ${name} and I am ${age} years old.;

Object Literals

Object literals are another way (as opposed to the class syntax) to create objects. For a simple examples there is no difference between the two. When we start adding methods however, then each copy of an object created trough literal carries a copy of all the methods which leads to a memory waste.

In the example bleow we create a simple object called person and add a method to it:

var person = {
  firstName: "John",
  lastName: "Doe",
  id: 5566,
  fullName: function() {
    return this.firstName + " " + this.lastName;
  }
};

person.fullName(); // "John Doe"

for...of

The for...of statement is used to iterate over iterable objects, arrays, and strings.

In the example below we will iterate over an array:

var array = [1, 2, 3, 4, 5];
for (var element of array) {
  console.log(element);
}

Modules

Modules are a way to organize code into separate files.

In the example below we will create a module called person_module and export a function called getFullName:

module.exports = function getFullName(person) {
  return person.firstName + " " + person.lastName;
};

Then we will import the module into another file:

var person_module = require("./person_module");
var person = {
  firstName: "John",
  lastName: "Doe"
};
var fullName = person_module.getFullName(person);
console.log(fullName); // "John Doe"

New Data Structures

The ES6+ standard included new data structures such as Map, WeakMap, Set, and WeakSet.

Let's first demonstrate the difference between Map and WeakMap:

var map = new Map();
var weakMap = new WeakMap();
// we will now add some data to the map using a function
(function() {
  var key = { extra: 5 }
  var value = 10
  map.set(key, value);
  weakMap.set(key, value);
})();

// now let us see what will happen when we try to read the data
console.log(map); // Map { { extra: 5 } => 10 }
console.log(weakMap); // WeakMap { <items unknown=""> }

When iterating over a Map, be cautious. If you use a standard for loop, you will get pairs of keys and values, but if you use forEach, you will get values first, then keys!

const map = new Map([
  ['A', 1],
  ['B', 2],
]);

for (const [k, v] of map) {
  console.log(k, v)
}
  
map.forEach((v, k) => {
  console.log(v, k) 
});

Subclassing Built-ins

We can now subclass the built-in types such as Array, Date, and RegExp.

Let's take a look at an example where we extend the Array class with a new method:

class SpecialArray extends Array {
  constructor(...args) {
    super(...args);
  }
  front() {
    return this[0];
  }
}

arr = new SpecialArray(1, 2, 3);
console.log(arr.front()); // 1

TypeScript

TypeScript is a superset of JavaScript that compiles to plain JavaScript. It introduces many new features such as classes, interfaces, generics, and more.

Some of the advantages of using TypeScript are:

Compilation

TypeScript has an integrated development environment that allows you to compile your code and see the errors that are generated.

Let's say we have a TypeScript file called app.ts and we want to compile it into a JavaScript file called app.js:

tsc app.ts --outFile app.js

The above command will compile the TypeScript file into JavaScript and output the result into the file app.js. You can now include the file in your HTML code since it's a plain old JavaScript.

Converting JavaScript projects to TypeScript projects

Let's assume that we already built a JavaScript project and we now decided to convert it to TypeScript.

  1. Create tsconfig.json file in the root directory of the project.

This file contains information used by the TypeScript compiler. A small example of the file is shown below:

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "sourceMap": true,
    "declaration": true,
    "declarationMap": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "lib": ["es5", "es6", "es2015.core", "es2015.promise", "es2015.iterable"]
  },
  "include": [
    "src/**/*.ts"
  ]
}

  1. Decide on a build tool to use.

Popular build tools include Webpack and Gulp. Webpack for example also uses configuration files to specify how to build the project. The configuration files are called webpack.config.js and look something like this:

module: {
    loaders: [
        { test: /\.ts$/, loader: 'ts-loader' }
    ]
}

  1. Change extension of all .js files to .ts.
  2. Refactor till you get rid of compilation errors.

Package managers

Package managers are used to install and manage dependencies. The chances are you won't be working with Vanilla JavaScript only. In fact you will probably be installing packages, libraries, and frameworks all the time. For that you will need a package manager.

NPM

NPM stands for "Node Package Manager," but don't be fooled by the term. React, SASS, Angular, Vue, and pretty much everything else can very certainly be installed and maintained using NPM.

To install the npm, download the installer from the official website.

To update NPM to the newest version, use:

npm install npm@latest -g

Initializing a project

In order to set up a project with NPM, you should use the following command:

npm init

It will create a package.json file in the root directory of your project. This file contains all important information about the project and its dependencies. Immediately after the command is executed, you will be prompted to enter the following information:

You can also use the --yes flag to skip the prompts.

The result of this process will look something like this:

{
  "name": "my-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "MIT",
  "dependencies": {
    "react": "16.3.2",
    "react-dom": "16.3.2"
  }
}

Installing a package

The most common way to install a package is to use the npm install command with different flags:

Using an existing project

If you downloaded a project from the internet and that project already has a package.json file, you can use the npm install command to install the dependencies.

Listing installed packages

In order to list all installed packages, you can use the npm list command:

Updating a package

Best Practices

General Guidelines

Variables and Constants

Functions

Loops and Iteration

Conditionals

Error Handling

Performance and Optimization

Asynchronous Programming

Testing and Code Quality

Table of Contents

    What is JavaScript?
    1. Skills Every JavaScript Developer Should Have
    2. Fundamentals
      1. Adding JavaScript to the HTML
      2. Null and Undefined
      3. Useful Built-In Methods
      4. Numbers
      5. Common Math Operations
      6. Comparison Operators
      7. Logical Operators
      8. Conditionals
      9. While Loops
      10. For Loops
    3. Functions
      1. Function Arguments
      2. The "return" Keyword
      3. ES6 Arrow Functions
      4. Scope
      5. Higher-Order Functions
    4. Arrays
      1. Copying Arrays
      2. Mutators
      3. Accessors
      4. Array Methods: Iterators
    5. Strings
      1. Common String Methods
    6. Classes
      1. Arrays vs Objects
    7. Exceptions
      1. Throwing Exceptions
      2. Try/Catch Blocks
      3. Types of Errors
    8. Dom
      1. DOM Element Selector Methods
      2. Edit DOM Elements
      3. DOM Events
    9. ES6+ Features
      1. Spread operator
      2. Destructuring
      3. Promises and Async/Await
      4. Template strings
      5. Object Literals
      6. for...of
      7. Modules
      8. New Data Structures
      9. Subclassing Built-ins
    10. TypeScript
      1. Compilation
      2. Converting JavaScript projects to TypeScript projects
    11. Package managers
      1. NPM
    12. Best Practices
      1. General Guidelines
      2. Variables and Constants
      3. Functions
      4. Loops and Iteration
      5. Conditionals
      6. Error Handling
      7. Performance and Optimization
      8. Asynchronous Programming
      9. Testing and Code Quality
    13. Links