Skip to main content

JavaScript

Getting Started

Package Management

pnpm init -y
# Creates a package.json file

# Add a dependency
pnpm add foo

# Add a dev dependency
pnpm add -D bar

# Install all dependencies
pnpm install

Run File

node myfile.js

Run Project

First, add a start script to your package.json file.

"scripts": {
"start": "node index.js"
}

Then, run the project.

pnpm start

Core Concepts

Declarations

  • let - mutable variable
  • const - immutable variable
  • var - old way to declare variables

Scopes

  • let and const are block scoped. A block is defined by curly braces {}
  • var is function scoped

Functions

  • Functions are first-class citizens
  • Can be assigned to variables, passed as arguments, and returned from other functions
  • In function declarations and expressions, if return is omitted, the function will return undefined.
  • In arrow functions, return can be implicitly returned if
    • the body is a single expression
    • AND the function is written without curly braces
// Function declaration (explicit return)
function greet(name) {
return `Hello, ${name}!`;
}

// Function expression (explicit return)
const greet = function(name) {
return `Hello, ${name}!`;
};

// Arrow function (implicit return)
const greet = (name) => `Hello, ${name}!`;

// Arrow function (explicit return)
const greet = (name) => { return `Hello, ${name}!` };

You can have parameters with default values with =.

// Default parameter
function greet(name = 'World') {
return `Hello, ${name}!`;
}

// Handling optional parameters manually
function greet(name) {
// Check if name is undefined
return `Hello, ${name || 'World'}!`;
}

Collections

Arrays

Arrays are ordered lists of values

const numbers = [1, 2, 3];

numbers[0] = 0; // Access/set by index

numbers.push(4); // Append to end
numbers.pop(); // Remove from end
numbers.shift(); // Remove from beginning
numbers.unshift(0); // Prepend to beginning

// Destructure array
const [first, second, third] = numbers;

// Swap
[first, second] = [second, first];

// Spread operator
const newNumbers = [1, 2, ...numbers];

There are many ways to loop through arrays.

// Loop
for (const number of numbers) {
console.log(number);
}
// Loop with index
for (let i = 0; i < numbers.length; i++) {
console.log(numbers[i]);
}

// forEach
numbers.forEach(number => {
console.log(number);
});
// forEach with index
numbers.forEach((number, index) => {
console.log(number, index);
});

Operations on arrays

// Map
const doubled = numbers.map(number => number * 2);
// [2, 4, 6]

// Filter
const evenNumbers = numbers.filter(number => number % 2 === 0);
// [2, 4]

// Reduce - accumulates
const sum = numbers.reduce((acc, number) => acc + number, 0);
// 6

Sets

  • Sets are ordered collections of unique values
const set = new Set();
set.add('John');
set.add('Jane');
set.add('John'); // Duplicate, ignored

set.has('John'); // true

set.size; // 2

set.delete('Jane');
set.clear();

Iterate over sets

for (const value of set) {
console.log(value);
}

Objects

  • Objects are unordered collections of key-value pairs
  • Keys are strings or symbols, and values can be any type
  • Use dot notation or bracket notation to access properties
const person = {
name: 'John',
age: 30,
};

// Access properties
person.name;
person['name'];

// Delete properties
delete person.age;

Loop through object properties

// Keys
for (const key in person) {
console.log(key, person[key]);
}
// Values
for (const value of Object.values(person)) {
console.log(value);
}
// Keys and values
for (const [key, value] of Object.entries(person)) {
console.log(key, value);
}

Maps

  • Maps are ordered collections of key-value pairs
  • Keys can be any type
const map = new Map();
map.set('name', 'John');
map.set('age', 30);

map.get('name'); // John
map.has('name'); // true

map.size; // 2

map.delete('age');
map.clear();

Asynchronous Code

Promises

// Creating a promise
const fetchData = new Promise((resolve, reject) => {
// Async operation
const success = true;
if (success) {
resolve('Data fetched successfully');
} else {
reject('Error fetching data');
}
});

// Using promises
fetchData
.then(data => console.log(data))
.catch(error => console.error(error));

Async/Await

// Async function declaration
async function fetchUser(id) {
try {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Error fetching user:', error);
throw error;
}
}

// Using async functions
fetchUser(123)
.then(user => console.log(user))
.catch(error => console.error(error));

Error Handling

Try/Catch

try {
// Code that might throw an error
} catch (error) {
// Code that runs if an error is thrown
} finally {
// Code that runs after the try/catch block
}

Throw

throw is equivalent to raise in Python.

throw new Error('Something went wrong');

Assert

// Node.js
const assert = require('assert');
assert(condition, 'Message');

// Or in testing frameworks like Jest
import { expect } from '@jest/globals';
expect(condition).toBeTruthy();

Type Checking

Checking class instances (supports inheritance)

class Animal {}
class Dog extends Animal {}

const d = new Dog();
console.log(d instanceof Dog); // true
console.log(d instanceof Animal); // true

Checking exact type (ignores inheritance)

console.log(Object.getPrototypeOf(d) === Dog.prototype);    // true
console.log(Object.getPrototypeOf(d) === Animal.prototype); // false

Checking primitives

let x = 42;
console.log(typeof x === "number"); // true

JavaScript vs Python Type Checking

  1. Python's isinstance is more flexible (works on both classes and built-in types), whereas TypeScript's instanceof only works for class instances.
  2. TypeScript's typeof is only for primitives, whereas Python's type() works on any object.
  3. Python supports multiple types in isinstance(obj, (type1, type2)), but TypeScript requires multiple typeof checks.

Testing

Jest

If you’re using Create React App (CRA), Jest and React Testing Library are already included. Otherwise, install the required dependencies:

npm install --save-dev jest @testing-library/react @testing-library/jest-dom @testing-library/user-event

Unit Testing

// src/components/Button.test.jsx
import { render, screen, fireEvent } from "@testing-library/react";
import Button from "./Button";

test("renders button with correct label", () => {
render(<Button label="Click Me" />);
expect(screen.getByText("Click Me")).toBeInTheDocument();
});

test("calls onClick handler when clicked", () => {
const handleClick = jest.fn(); // Mock function
render(<Button label="Click Me" onClick={handleClick} />);

fireEvent.click(screen.getByText("Click Me"));

expect(handleClick).toHaveBeenCalledTimes(1);
});
npm test

Integration Testing

// src/components/Counter.test.jsx
import { render, screen, fireEvent } from "@testing-library/react";
import Counter from "./Counter";

test("increments counter when button is clicked", () => {
render(<Counter />);

const button = screen.getByText("Increment");
fireEvent.click(button);

expect(screen.getByText("Count: 1")).toBeInTheDocument();
});