Introduction to JavaScript
JavaScript is a high-level, interpreted programming language that conforms to the ECMAScript specification. It is a language that is also characterized as dynamic, weakly typed, prototype-based, and multi-paradigm.
JavaScript Timeline
- 1995 - JavaScript was created by Brendan Eich at Netscape
- 1997 - ECMAScript 1 (ES1) was released
- 1998 - ECMAScript 2 (ES2) was released
- 1999 - ECMAScript 3 (ES3) was released
- 2009 - ECMAScript 5 (ES5) was released
- 2015 - ECMAScript 2015 (ES6) was released with major new features
- 2016-Present - Annual releases (ES2016, ES2017, etc.) with incremental updates
JavaScript was originally designed to add interactivity to web pages, but it has evolved into a versatile language used for both client-side and server-side development. Today, JavaScript powers everything from simple web animations to complex single-page applications, mobile apps, desktop applications, and even server-side applications.
How JavaScript Works
JavaScript is primarily a client-side language, which means it runs in the user's browser rather than on the web server. When a web page is loaded, the browser creates a Document Object Model (DOM) of the page, which JavaScript can then manipulate.
JavaScript is an interpreted language, which means the code is executed line by line, rather than being compiled before execution. Modern browsers use Just-In-Time (JIT) compilation to improve performance.
JavaScript, HTML, and CSS
JavaScript works alongside HTML and CSS to create interactive web pages:
- HTML - Provides the structure and content of web pages
- CSS - Controls the presentation and layout of web pages
- JavaScript - Adds interactivity and dynamic behavior to web pages
JavaScript Environments
JavaScript can run in various environments:
- Browsers - Chrome, Firefox, Safari, Edge, etc.
- Node.js - A JavaScript runtime built on Chrome's V8 JavaScript engine for server-side development
- Deno - A secure runtime for JavaScript and TypeScript
- Electron - A framework for building desktop applications with JavaScript, HTML, and CSS
- React Native - A framework for building native mobile applications using JavaScript
JavaScript Basics
Before diving into the details, let's understand the basic concepts of JavaScript.
Adding JavaScript to HTML
There are three ways to add JavaScript to an HTML document:
1. Internal JavaScript
<script>
// JavaScript code goes here
document.getElementById("demo").innerHTML = "Hello, World!";
</script>
2. External JavaScript
<script src="script.js"></script>
3. Inline JavaScript
<button onclick="alert('Hello, World!')">Click Me</button>
JavaScript Syntax
JavaScript syntax is the set of rules that define how JavaScript programs are constructed.
Statements
JavaScript statements are commands to the browser. They are composed of values, operators, expressions, keywords, and comments.
// This is a statement
let x = 5;
// This is another statement
console.log("Hello, World!");
// Multiple statements can be grouped in a block using curly braces
{
let x = 5;
console.log(x);
}
Comments
Comments are used to explain JavaScript code and make it more readable. They are ignored by the browser.
// This is a single-line comment
/* This is a
multi-line comment */
Variables
Variables are containers for storing data values. In JavaScript, there are three ways to declare a variable:
// Using var (function-scoped, older way)
var x = 5;
// Using let (block-scoped, introduced in ES6)
let y = 10;
// Using const (block-scoped, constant value, introduced in ES6)
const z = 15;
Operators
JavaScript operators are symbols that are used to perform operations on operands.
Type | Operators | Example |
---|---|---|
Arithmetic | +, -, *, /, %, **, ++, -- | let sum = 5 + 10; |
Assignment | =, +=, -=, *=, /=, %=, **= | let x = 10; x += 5; |
Comparison | ==, ===, !=, !==, >, <, >=, <= | if (x === 10) { } |
Logical | &&, ||, ! | if (x > 5 && y < 10) { } |
String | +, += | let greeting = "Hello" + " " + "World"; |
Conditional (Ternary) | ?: | let status = (age >= 18) ? "Adult" : "Minor"; |
Control Structures
Control structures are used to control the flow of execution in a program.
// if statement
if (condition) {
// code to be executed if condition is true
} else if (anotherCondition) {
// code to be executed if anotherCondition is true
} else {
// code to be executed if no condition is true
}
// switch statement
switch (expression) {
case value1:
// code to be executed if expression === value1
break;
case value2:
// code to be executed if expression === value2
break;
default:
// code to be executed if expression doesn't match any case
}
// for loop
for (let i = 0; i < 5; i++) {
// code to be executed 5 times
}
// while loop
let i = 0;
while (i < 5) {
// code to be executed as long as i < 5
i++;
}
// do...while loop
let i = 0;
do {
// code to be executed at least once, then as long as i < 5
i++;
} while (i < 5);
// for...in loop (for objects)
for (let key in object) {
// code to be executed for each key in object
}
// for...of loop (for iterables like arrays)
for (let value of array) {
// code to be executed for each value in array
}
For more detailed information on JavaScript basics, visit our JavaScript Basics page.
JavaScript Data Types
JavaScript has several built-in data types that can be categorized as primitive and non-primitive (reference) types.
Primitive Data Types
Primitive data types are immutable (cannot be changed) and are passed by value.
Data Type | Description | Example |
---|---|---|
String | Represents textual data | "Hello, World!" , 'JavaScript' |
Number | Represents numeric values | 42 , 3.14 , NaN , Infinity |
Boolean | Represents logical values | true , false |
Undefined | Represents a variable that has been declared but not assigned a value | undefined |
Null | Represents the intentional absence of any object value | null |
Symbol | Represents a unique identifier | Symbol('description') |
BigInt | Represents integers larger than the Number type can handle | 9007199254740991n |
Non-Primitive (Reference) Data Types
Non-primitive data types are mutable (can be changed) and are passed by reference.
Data Type | Description | Example |
---|---|---|
Object | Represents a collection of related data | { name: "John", age: 30 } |
Array | Represents a list-like collection of values | [1, 2, 3, 4] |
Function | Represents a reusable block of code | function() { return "Hello"; } |
Date | Represents a date and time | new Date() |
RegExp | Represents a regular expression | /pattern/ |
Map | Represents a collection of key-value pairs | new Map() |
Set | Represents a collection of unique values | new Set() |
Type Conversion
JavaScript is a loosely typed language, which means variables can change types. There are two types of type conversion:
Implicit Conversion (Type Coercion)
let result = "5" + 2; // "52" (number is converted to string)
console.log(result);
result = "5" - 2; // 3 (string is converted to number)
console.log(result);
result = "5" * "2"; // 10 (both strings are converted to numbers)
console.log(result);
result = 5 + true; // 6 (true is converted to 1)
console.log(result);
result = 5 + false; // 5 (false is converted to 0)
console.log(result);
Explicit Conversion
// String to Number
let num = Number("5"); // 5
console.log(num);
// Number to String
let str = String(5); // "5"
console.log(str);
// Value to Boolean
let bool = Boolean(0); // false
console.log(bool);
bool = Boolean(1); // true
console.log(bool);
bool = Boolean(""); // false
console.log(bool);
bool = Boolean("Hello"); // true
console.log(bool);
Arrays
Arrays are used to store multiple values in a single variable. They are zero-indexed, meaning the first element is at index 0.
// Creating an array
let fruits = ["Apple", "Banana", "Orange"];
// Accessing array elements
let firstFruit = fruits[0]; // "Apple"
// Modifying array elements
fruits[1] = "Mango"; // Now fruits is ["Apple", "Mango", "Orange"]
// Array length
let length = fruits.length; // 3
// Array methods
fruits.push("Pineapple"); // Add to the end
fruits.pop(); // Remove from the end
fruits.unshift("Strawberry"); // Add to the beginning
fruits.shift(); // Remove from the beginning
fruits.splice(1, 1, "Kiwi"); // Remove 1 element at index 1 and add "Kiwi"
let newFruits = fruits.slice(1, 3); // Create a new array from index 1 to 2
let combined = fruits.concat(["Grape", "Watermelon"]); // Combine arrays
let joined = fruits.join(", "); // Join elements into a string
let index = fruits.indexOf("Orange"); // Find the index of an element
let includes = fruits.includes("Apple"); // Check if an element exists
Strings
Strings are used to store and manipulate text. They are immutable, meaning they cannot be changed once created.
// Creating a string
let text = "Hello, World!";
// String length
let length = text.length; // 13
// Accessing characters
let firstChar = text[0]; // "H"
let lastChar = text[text.length - 1]; // "!"
// String methods
let upperCase = text.toUpperCase(); // "HELLO, WORLD!"
let lowerCase = text.toLowerCase(); // "hello, world!"
let substring = text.substring(0, 5); // "Hello"
let replaced = text.replace("World", "JavaScript"); // "Hello, JavaScript!"
let split = text.split(", "); // ["Hello", "World!"]
let trimmed = " Hello ".trim(); // "Hello"
let includes = text.includes("World"); // true
let startsWith = text.startsWith("Hello"); // true
let endsWith = text.endsWith("!"); // true
let indexOf = text.indexOf("World"); // 7
let charAt = text.charAt(0); // "H"
JavaScript Functions
Functions are one of the fundamental building blocks in JavaScript. A function is a reusable block of code designed to perform a particular task.
Function Declaration
A function declaration defines a named function.
function greet(name) {
return "Hello, " + name + "!";
}
// Calling the function
let message = greet("John");
console.log(message); // "Hello, John!"
Function Expression
A function expression defines a function as part of a larger expression, typically a variable assignment.
let greet = function(name) {
return "Hello, " + name + "!";
};
// Calling the function
let message = greet("John");
console.log(message); // "Hello, John!"
Arrow Functions
Arrow functions provide a shorter syntax for writing function expressions. They were introduced in ES6.
let greet = (name) => {
return "Hello, " + name + "!";
};
// Shorter syntax for simple functions
let greetShort = name => "Hello, " + name + "!";
// Calling the function
let message = greet("John");
console.log(message); // "Hello, John!"
Function Parameters
Function parameters are the names listed in the function definition. Function arguments are the real values passed to the function.
// Function with multiple parameters
function add(a, b) {
return a + b;
}
let sum = add(5, 3);
console.log(sum); // 8
// Default parameters (ES6)
function greet(name = "Guest") {
return "Hello, " + name + "!";
}
console.log(greet()); // "Hello, Guest!"
console.log(greet("John")); // "Hello, John!"
// Rest parameters (ES6)
function sum(...numbers) {
let total = 0;
for (let number of numbers) {
total += number;
}
return total;
}
console.log(sum(1, 2, 3, 4, 5)); // 15
Scope
Scope determines the accessibility of variables, objects, and functions from different parts of the code.
// Global scope
let globalVar = "I am global";
function myFunction() {
// Function scope
let functionVar = "I am function-scoped";
console.log(globalVar); // "I am global"
if (true) {
// Block scope (with let and const)
let blockVar = "I am block-scoped";
const blockConst = "I am also block-scoped";
var functionScopedVar = "I am function-scoped, not block-scoped";
console.log(blockVar); // "I am block-scoped"
}
// console.log(blockVar); // Error: blockVar is not defined
// console.log(blockConst); // Error: blockConst is not defined
console.log(functionScopedVar); // "I am function-scoped, not block-scoped"
}
myFunction();
// console.log(functionVar); // Error: functionVar is not defined
Closures
A closure is the combination of a function bundled together with references to its surrounding state (the lexical environment).
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
let counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
Higher-Order Functions
Higher-order functions are functions that take other functions as arguments or return functions as their results.
// Function that takes a function as an argument
function doOperation(x, y, operation) {
return operation(x, y);
}
let sum = doOperation(5, 3, function(a, b) {
return a + b;
});
console.log(sum); // 8
// Function that returns a function
function createMultiplier(factor) {
return function(number) {
return number * factor;
};
}
let double = createMultiplier(2);
let triple = createMultiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
JavaScript Objects
Objects are collections of key-value pairs. They are used to store related data and functionality.
Creating Objects
There are several ways to create objects in JavaScript:
// Object literal
let person = {
firstName: "John",
lastName: "Doe",
age: 30,
fullName: function() {
return this.firstName + " " + this.lastName;
}
};
// Using the new Object() syntax
let car = new Object();
car.make = "Toyota";
car.model = "Corolla";
car.year = 2020;
// Using a constructor function
function Book(title, author, year) {
this.title = title;
this.author = author;
this.year = year;
this.getSummary = function() {
return `${this.title} was written by ${this.author} in ${this.year}`;
};
}
let book = new Book("The Hobbit", "J.R.R. Tolkien", 1937);
// Using Object.create()
let animal = {
type: "Animal",
displayType: function() {
console.log(this.type);
}
};
let dog = Object.create(animal);
dog.type = "Dog";
Accessing Object Properties
There are two ways to access object properties:
// Dot notation
let firstName = person.firstName;
// Bracket notation
let lastName = person["lastName"];
Object Methods
Object methods are functions that are stored as object properties.
let person = {
firstName: "John",
lastName: "Doe",
fullName: function() {
return this.firstName + " " + this.lastName;
}
};
// Calling the method
console.log(person.fullName()); // "John Doe"
// Shorthand method syntax (ES6)
let calculator = {
add(a, b) {
return a + b;
},
subtract(a, b) {
return a - b;
}
};
console.log(calculator.add(5, 3)); // 8
Prototypes and Inheritance
JavaScript uses prototypal inheritance, where objects inherit properties and methods from other objects.
// Constructor function
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
// Adding a method to the prototype
Person.prototype.fullName = function() {
return this.firstName + " " + this.lastName;
};
let person1 = new Person("John", "Doe");
let person2 = new Person("Jane", "Smith");
console.log(person1.fullName()); // "John Doe"
console.log(person2.fullName()); // "Jane Smith"
// Inheritance
function Student(firstName, lastName, school) {
Person.call(this, firstName, lastName);
this.school = school;
}
// Inherit the Person prototype
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
// Add a method to Student prototype
Student.prototype.getSchool = function() {
return this.school;
};
let student = new Student("Alice", "Johnson", "MIT");
console.log(student.fullName()); // "Alice Johnson"
console.log(student.getSchool()); // "MIT"
Classes (ES6)
ES6 introduced a class syntax that provides a clearer and more concise way to create objects and deal with inheritance.
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
fullName() {
return this.firstName + " " + this.lastName;
}
}
let person = new Person("John", "Doe");
console.log(person.fullName()); // "John Doe"
// Inheritance with classes
class Student extends Person {
constructor(firstName, lastName, school) {
super(firstName, lastName);
this.school = school;
}
getSchool() {
return this.school;
}
}
let student = new Student("Alice", "Johnson", "MIT");
console.log(student.fullName()); // "Alice Johnson"
console.log(student.getSchool()); // "MIT"
Document Object Model (DOM)
The Document Object Model (DOM) is a programming interface for HTML and XML documents. It represents the page so that programs can change the document structure, style, and content.
Accessing DOM Elements
There are several ways to access DOM elements:
// By ID
let element = document.getElementById("myId");
// By class name
let elements = document.getElementsByClassName("myClass");
// By tag name
let paragraphs = document.getElementsByTagName("p");
// By CSS selector (returns the first matching element)
let element = document.querySelector(".myClass");
// By CSS selector (returns all matching elements)
let elements = document.querySelectorAll("p.intro");
Modifying DOM Elements
Once you have accessed a DOM element, you can modify its content, attributes, and style:
// Changing content
element.textContent = "New text content";
element.innerHTML = "New HTML content";
// Changing attributes
element.setAttribute("class", "newClass");
element.id = "newId";
// Changing style
element.style.color = "red";
element.style.fontSize = "20px";
element.style.display = "none";
Creating and Removing Elements
You can create new elements and add them to the DOM, or remove existing elements:
// Creating a new element
let newElement = document.createElement("div");
newElement.textContent = "New element";
// Adding the element to the DOM
document.body.appendChild(newElement);
// Inserting before another element
let referenceElement = document.getElementById("reference");
document.body.insertBefore(newElement, referenceElement);
// Removing an element
let elementToRemove = document.getElementById("remove");
elementToRemove.parentNode.removeChild(elementToRemove);
// Modern way to remove an element
elementToRemove.remove();
Event Handling
Events are actions that occur in the browser, such as a user clicking a button or a page finishing loading. You can use JavaScript to respond to these events:
// Using addEventListener
let button = document.getElementById("myButton");
button.addEventListener("click", function(event) {
console.log("Button clicked!");
console.log(event);
});
// Removing an event listener
function handleClick(event) {
console.log("Button clicked!");
}
button.addEventListener("click", handleClick);
button.removeEventListener("click", handleClick);
// Event delegation
document.getElementById("parent").addEventListener("click", function(event) {
if (event.target.matches(".child")) {
console.log("Child element clicked!");
}
});
Common DOM Events
Event | Description |
---|---|
click | Occurs when the element is clicked |
dblclick | Occurs when the element is double-clicked |
mouseenter | Occurs when the mouse pointer enters the element |
mouseleave | Occurs when the mouse pointer leaves the element |
keydown | Occurs when a key is pressed down |
keyup | Occurs when a key is released |
submit | Occurs when a form is submitted |
load | Occurs when an object has loaded |
resize | Occurs when the browser window is resized |
scroll | Occurs when the user scrolls in the specified element |
Asynchronous JavaScript
Asynchronous programming allows you to execute code without blocking the main thread. This is essential for operations like fetching data from a server or reading a file.
Callbacks
A callback is a function passed as an argument to another function, which is then invoked inside the outer function.
function fetchData(callback) {
setTimeout(function() {
const data = { name: "John", age: 30 };
callback(data);
}, 1000);
}
fetchData(function(data) {
console.log(data); // { name: "John", age: 30 }
});
Promises
Promises provide a cleaner way to handle asynchronous operations. A promise represents a value that may not be available yet.
function fetchData() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
const data = { name: "John", age: 30 };
// Simulate successful operation
resolve(data);
// Or simulate an error
// reject(new Error("Failed to fetch data"));
}, 1000);
});
}
fetchData()
.then(function(data) {
console.log(data); // { name: "John", age: 30 }
return data.name;
})
.then(function(name) {
console.log(name); // "John"
})
.catch(function(error) {
console.error(error);
})
.finally(function() {
console.log("Operation completed");
});
Async/Await
Async/await is a syntactic sugar on top of promises, making asynchronous code look and behave more like synchronous code.
async function fetchData() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
const data = { name: "John", age: 30 };
resolve(data);
}, 1000);
});
}
async function displayData() {
try {
const data = await fetchData();
console.log(data); // { name: "John", age: 30 }
const name = data.name;
console.log(name); // "John"
} catch (error) {
console.error(error);
} finally {
console.log("Operation completed");
}
}
displayData();
Fetch API
The Fetch API provides a modern interface for fetching resources across the network.
// Using promises
fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
console.log(data);
})
.catch(error => {
console.error('Fetch error:', error);
});
// Using async/await
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Fetch error:', error);
}
}
fetchData();
ES6+ Features
ECMAScript 2015 (ES6) and later versions introduced many new features to JavaScript. Here are some of the most important ones:
let and const
Block-scoped variables and constants.
// let - block-scoped variable
let x = 10;
if (true) {
let x = 20; // Different variable
console.log(x); // 20
}
console.log(x); // 10
// const - block-scoped constant
const PI = 3.14159;
// PI = 3.14; // Error: Assignment to constant variable
Arrow Functions
A shorter syntax for writing function expressions.
// Traditional function expression
let add = function(a, b) {
return a + b;
};
// Arrow function
let add = (a, b) => a + b;
// Arrow function with no parameters
let sayHello = () => "Hello";
// Arrow function with one parameter
let double = x => x * 2;
Template Literals
String literals that allow embedded expressions.
let name = "John";
let age = 30;
// Traditional string concatenation
let message = "My name is " + name + " and I am " + age + " years old.";
// Template literal
let message = `My name is ${name} and I am ${age} years old.`;
// Multi-line strings
let multiLine = `This is a
multi-line
string`;
Destructuring Assignment
A syntax that allows you to extract data from arrays or objects into distinct variables.
// Array destructuring
let [a, b] = [1, 2];
console.log(a); // 1
console.log(b); // 2
// Object destructuring
let person = { name: "John", age: 30 };
let { name, age } = person;
console.log(name); // "John"
console.log(age); // 30
// With different variable names
let { name: personName, age: personAge } = person;
console.log(personName); // "John"
console.log(personAge); // 30
// Default values
let { name, age, gender = "unknown" } = person;
console.log(gender); // "unknown"
Spread and Rest Operators
The spread operator (...) allows an iterable to be expanded in places where zero or more arguments or elements are expected. The rest operator collects multiple elements into a single array.
// Spread operator with arrays
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]
// Spread operator with objects
let obj1 = { a: 1, b: 2 };
let obj2 = { c: 3, d: 4 };
let combined = { ...obj1, ...obj2 }; // { a: 1, b: 2, c: 3, d: 4 }
// Rest operator in function parameters
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 15
// Rest operator in destructuring
let [first, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(rest); // [2, 3, 4, 5]
Default Parameters
Default function parameters allow parameters to be initialized with default values if no value or undefined is passed.
function greet(name = "Guest", greeting = "Hello") {
return `${greeting}, ${name}!`;
}
console.log(greet()); // "Hello, Guest!"
console.log(greet("John")); // "Hello, John!"
console.log(greet("John", "Hi")); // "Hi, John!"
Classes
ES6 introduced a class syntax that provides a clearer and more concise way to create objects and deal with inheritance.
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
return `Hello, my name is ${this.name}`;
}
// Static method
static createAnonymous() {
return new Person("Anonymous", 0);
}
// Getter
get ageInMonths() {
return this.age * 12;
}
// Setter
set ageInMonths(months) {
this.age = months / 12;
}
}
let person = new Person("John", 30);
console.log(person.greet()); // "Hello, my name is John"
let anonymous = Person.createAnonymous();
console.log(anonymous.name); // "Anonymous"
console.log(person.ageInMonths); // 360
person.ageInMonths = 360;
console.log(person.age); // 30
Modules
ES6 modules allow you to split your code into separate files, making it more maintainable.
// math.js
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
export const PI = 3.14159;
// main.js
import { add, subtract, PI } from './math.js';
console.log(add(5, 3)); // 8
console.log(subtract(5, 3)); // 2
console.log(PI); // 3.14159
// Import everything
import * as math from './math.js';
console.log(math.add(5, 3)); // 8
// Default export
// utils.js
export default function() {
console.log("Default export");
}
// main.js
import myFunction from './utils.js';
myFunction(); // "Default export"
JavaScript Best Practices
Following best practices ensures that your JavaScript code is maintainable, efficient, and performs well.
Code Style
- Use consistent indentation (2 or 4 spaces)
- Use semicolons at the end of statements
- Use camelCase for variables and functions
- Use PascalCase for constructor functions and classes
- Use UPPERCASE for constants
- Use meaningful variable and function names
- Keep functions small and focused on a single task
- Use comments to explain complex code
Performance
- Minimize DOM manipulation
- Use event delegation for handling multiple similar events
- Avoid global variables
- Use modern array methods (map, filter, reduce) instead of loops when appropriate
- Use debounce or throttle for expensive operations
- Optimize loops by caching the length of arrays
- Use Web Workers for CPU-intensive tasks
Security
- Validate user input
- Avoid using eval()
- Use Content Security Policy (CSP)
- Be cautious with innerHTML (use textContent when possible)
- Sanitize data before inserting it into the DOM
- Use HTTPS for external resources
- Be careful with third-party libraries
Error Handling
- Use try-catch blocks for error handling
- Provide meaningful error messages
- Log errors for debugging
- Handle promise rejections
- Use finally blocks for cleanup
// Good error handling
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error('Fetch error:', error);
// Handle the error appropriately
throw error; // Re-throw if needed
} finally {
// Cleanup code
}
}
Testing
- Write unit tests for your code
- Use testing frameworks like Jest, Mocha, or Jasmine
- Test edge cases
- Use test-driven development (TDD) when appropriate
- Use continuous integration (CI) for automated testing
Modern JavaScript
- Use ES6+ features when possible
- Use let and const instead of var
- Use arrow functions for shorter syntax
- Use template literals for string interpolation
- Use destructuring assignment
- Use spread and rest operators
- Use async/await for asynchronous code
- Use modules to organize your code
Debugging
- Use console.log() for basic debugging
- Use console.table() for tabular data
- Use console.time() and console.timeEnd() for performance measurement
- Use debugger statement for breakpoints
- Use browser developer tools
- Use source maps for debugging minified code
Additional Resources
Here are some valuable resources for learning more about JavaScript:
Documentation
Tutorials and Guides
Tools
- ESLint - A tool for identifying and reporting on patterns in JavaScript
- Prettier - An opinionated code formatter
- Babel - A JavaScript compiler
- Webpack - A module bundler
Books
- "JavaScript: The Good Parts" by Douglas Crockford
- "Eloquent JavaScript" by Marijn Haverbeke
- "You Don't Know JS" series by Kyle Simpson
- "JavaScript: The Definitive Guide" by David Flanagan