Skip to content

es6_quick_guide

ECMAScript (ES) is a scripting language specification standardized by ECMA International. It forms the basis of JavaScript. ES6, officially known as ECMAScript 2015, was a significant update that introduced many new features to the language, making JavaScript more powerful and expressive. Subsequent yearly releases (ES2016, ES2017, etc.) continue to add features.

This tutorial provides a quick overview of key ES6 features and related modern JavaScript concepts.

JavaScript was created by Brendan Eich at Netscape in 1995. It is a high-level, often just-in-time compiled, multi-paradigm language that conforms to the ECMAScript specification. It is primarily known as the scripting language for Web pages, but it’s also used in many non-browser environments thanks to Node.js.

Key ES6 (ECMAScript 2015) Features Covered:

Section titled “Key ES6 (ECMAScript 2015) Features Covered:”
  • Constants (const) and Block-Scoped Variables (let)
  • Arrow Functions
  • Default Parameter Values
  • Rest and Spread Parameters/Syntax
  • Template Literals
  • Enhanced Object Literals (shorthand properties, method definitions)
  • Destructuring Assignment (Arrays and Objects)
  • Modules (import/export)
  • Classes (class syntax)
  • Iterators and Generators (function*, yield)
  • Collections (Map, Set, WeakMap, WeakSet)
  • Promises (for asynchronous programming)
  • New built-in methods for various objects (String, Array, Number, Math, Object)

To write and run ES6+ JavaScript code, you have several options:

All modern web browsers (Chrome, Firefox, Safari, Edge) have excellent support for ES6 and later features. You can write ES6 code directly in <script> tags or in .js files linked to your HTML. Browser developer tools (accessed usually by pressing F12) provide a console to experiment with JavaScript and debug your code.

Node.js is a JavaScript runtime environment that allows you to run JavaScript code outside of a browser, typically for server-side applications, command-line tools, and build scripts. Recent versions of Node.js have strong support for ES6+ features.

Visit the official Node.js website (https://nodejs.org/) to download the installer for your operating system (Windows, macOS, Linux). It’s recommended to install the LTS (Long Term Support) version for stability. The installation typically includes npm (Node Package Manager), which is used to manage project dependencies and run scripts.

After installation, you can verify it by opening your terminal or command prompt and typing:

node -v
npm -v

This will display the installed versions of Node.js and npm.

A good code editor or Integrated Development Environment (IDE) will significantly improve your development experience with features like syntax highlighting, code completion, debugging tools, and Git integration. Popular choices for JavaScript development include:

  • Visual Studio Code (VS Code): Free, open-source, highly popular, and feature-rich. Excellent JavaScript/TypeScript support and a vast extension marketplace. Available at https://code.visualstudio.com/.
  • WebStorm: A powerful commercial IDE from JetBrains, specifically designed for JavaScript and related technologies.
  • Sublime Text: A lightweight and fast editor, extensible with packages.
  • Atom: A hackable text editor built by GitHub, free and open-source.

If you need to support older browsers or environments that don’t fully support ES6+, you can use a transpiler like Babel (https://babeljs.io/). Babel converts modern JavaScript code (ES6+) into older, more widely compatible versions (e.g., ES5). This is often part of a build process using tools like Webpack, Parcel, or Rollup.

JavaScript syntax defines the rules for writing valid programs. Key components include:

  • Variables: Named containers for storing data. Declared using let, const (ES6+), or var (older style).
  • Literals: Fixed values directly written in the code (e.g., 100, "hello", true, null, [1, 2], {a:1}).
  • Operators: Symbols that perform operations on values (e.g., +, -, *, /, =, ===, &&, ||).
  • Keywords: Reserved words with special meaning (e.g., if, for, function, class, return, let, const).
  • Comments: Ignored by the interpreter, used for explaining code. Single-line (// ...) and multi-line (/* ... */).
  • Identifiers: Names for variables, functions, classes, etc. Rules: - Must start with a letter, underscore (_), or dollar sign ($). - Subsequent characters can be letters, digits, underscores, or dollar signs. - Case-sensitive (e.g., myVar and myvar are different). - Cannot be a reserved keyword.
  • Statements: Instructions to be executed. Typically end with a semicolon (;).
  • Blocks: Groups of statements enclosed in curly braces ({}).

break, case, catch, class, const, continue, debugger, default, delete, do, else, export, extends, false, finally, for, function, if, import, in, instanceof, let, new, null, return, super, switch, this, throw, true, try, typeof, var (legacy), void, while, with (discouraged), yield. (Note: enum, implements, interface, package, private, protected, public, static are reserved for future use, though static is used within classes.)

JavaScript largely ignores whitespace (spaces, tabs, newlines) between tokens, allowing flexible code formatting. However, whitespace can be significant in some contexts (e.g., within string literals).

Semicolons (;) are used to terminate statements. While JavaScript has Automatic Semicolon Insertion (ASI), which attempts to insert semicolons where they are missing, it’s a best practice to explicitly include them to avoid ambiguity and potential errors.

console.log("Hello ES6");
console.log("Multiple statements on one line require semicolons:"); let x = 5; let y = 10;

Strict Mode ("use strict";) is a way to opt into a restricted variant of JavaScript. It helps catch common coding errors and prevents or throws errors for certain unsafe actions. It can be applied to entire scripts or individual functions.

"use strict";
// Example of an error in strict mode:
// undeclaredVariable = "This would throw an error";
function strictFunction() {
"use strict";
// Function-level strict mode
// anotherUndeclared = "Error here too";
}
console.log("Strict mode is active globally in this example if at top of file.");

Note: ES6 modules are implicitly in strict mode.

Variables are named storage for data. ES6 introduced let and const for variable declaration, offering better scoping and control compared to the older var keyword.

  • Declares a block-scoped local variable, optionally initializing it to a value.
  • Block scope means the variable is only accessible within the block ({...}) it’s defined in (e.g., inside an if statement, for loop, or a standalone block).
  • Variables declared with let cannot be re-declared within the same scope.
  • They are hoisted to the top of their block but are not initialized until the declaration is encountered (Temporal Dead Zone - TDZ). Accessing them before declaration results in a ReferenceError.
let count = 10;
if (count > 5) {
let message = "Greater than 5"; // block-scoped
console.log(message);
}
// console.log(message); // ReferenceError: message is not defined here
count = 20; // Allowed
// let count = 30; // SyntaxError: Identifier 'count' has already been declared
  • Declares a block-scoped constant.
  • Must be initialized at the time of declaration.
  • Its value cannot be re-assigned after initialization.
  • Like let, const variables are block-scoped and are in a TDZ before declaration.
  • For objects and arrays declared with const, the variable itself cannot be reassigned to a new object/array, but the properties of the object or elements of the array can be modified.
const PI = 3.14159;
// PI = 3.14; // TypeError: Assignment to constant variable.
const person = {
name: "Alice",
age: 30
};
person.age = 31; // Allowed: Mutating the object's property
console.log(person);
// person = { name: "Bob" }; // TypeError: Assignment to constant variable.
  • Declares a function-scoped or globally-scoped variable.
  • Variables declared with var are hoisted to the top of their function or global scope and initialized with undefined.
  • Can be re-declared within the same scope without error.

It’s generally recommended to use let and const in modern JavaScript for clearer scoping and to avoid common pitfalls associated with var.

Operators are symbols that perform operations on operands (values or variables).

+ (Addition), - (Subtraction), * (Multiplication), / (Division), % (Modulus/Remainder), ** (Exponentiation - ES2016), ++ (Increment), -- (Decrement).

= (Assignment), +=, -=, *=, /=, %=, **=.

== (Equal to, type coercion), != (Not equal to, type coercion), === (Strictly equal to, no type coercion), !== (Strictly not equal to, no type coercion), > (Greater than), < (Less than), >= (Greater than or equal to), <= (Less than or equal to). Always prefer === and !== over == and != to avoid unexpected behavior due to type coercion.

&& (Logical AND), || (Logical OR), ! (Logical NOT).

& (AND), | (OR), ^ (XOR), ~ (NOT), << (Left shift), >> (Sign-propagating right shift), >>> (Zero-fill right shift).

condition ? exprIfTrue : exprIfFalse

typeof (Returns a string indicating the type of an operand), instanceof (Checks if an object is an instance of a particular class or constructor).

Spread (...) and Rest (...) Operators (ES6):

Section titled “Spread (...) and Rest (...) Operators (ES6):”
  • Spread Syntax: Expands an iterable (like an array or string) into individual elements, or an object into key-value pairs. Used in function calls, array literals, and object literals.
  • Rest Parameter: Collects an indefinite number of arguments into an array. Used in function parameter lists.
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // Spread: [1, 2, 3, 4, 5]
function sum(...numbers) { // Rest
return numbers.reduce((acc, current) => acc + current, 0);
}
console.log(sum(1, 2, 3, 4)); // Output: 10

Decision-making constructs allow your code to execute different blocks of statements based on conditions.

Executes a block of code if a specified condition is true.

Executes one block of code if the condition is true, and another block if it’s false.

Tests multiple conditions sequentially and executes the block corresponding to the first true condition.

let score = 85;
if (score >= 90) {
console.log("Grade: A");
} else if (score >= 80) {
console.log("Grade: B"); // This will be executed
} else if (score >= 70) {
console.log("Grade: C");
} else {
console.log("Grade: F");
}

Evaluates an expression and matches its value against a series of case clauses. Executes the statements associated with the matched case. break statements are typically used to exit the switch; otherwise, execution falls through to subsequent cases.

let day = "Monday";
switch (day) {
case "Saturday":
case "Sunday":
console.log("It's the weekend!");
break;
case "Monday":
console.log("Start of the work week.");
break;
default:
console.log("It's a weekday.");
}

Loops are used to execute a block of code repeatedly.

Repeats a block of code a known number of times. Consists of initialization, condition, and final-expression (increment/decrement).

for (let i = 0; i < 5; i++) {
console.log(`Iteration ${i}`);
}

Repeats a block of code as long as a specified condition is true. The condition is checked before each iteration.

Similar to while, but the condition is checked after each iteration, so the code block always executes at least once.

Iterates over the enumerable string properties of an object (including inherited properties). For arrays, it iterates over indices. Generally not recommended for iterating over arrays if order matters or if you only want own properties; use for...of or array methods like forEach instead for arrays.

const person = { name: "John", age: 30 };
for (const key in person) {
if (person.hasOwnProperty(key)) { // Good practice to check for own properties
console.log(`${key}: ${person[key]}`);
}
}

Iterates over the values of iterable objects (like Arrays, Strings, Maps, Sets, etc.). This is the preferred way to loop over array elements if you need the values directly.

const colors = ["red", "green", "blue"];
for (const color of colors) {
console.log(color);
}

Loop Control Statements: break (exits the loop) and continue (skips the current iteration and proceeds to the next).

Functions are blocks of reusable code that perform a specific task. ES6 introduced several enhancements to functions.

function greet(name) {
return `Hello, ${name}!`;
}
console.log(greet("World"));
const greet = function(name) {
return `Hello, ${name}!`;
};
console.log(greet("World"));

Provide a concise syntax for writing functions. They lexically bind the this value, meaning this refers to the this of the enclosing scope. They are not suitable for methods that need their own this context (like object methods that refer to the object itself) or constructors.

const add = (a, b) => a + b;
console.log(add(5, 3)); // 8
const square = x => x * x; // Parentheses optional for single parameter
console.log(square(4)); // 16
const numbers = [1, 2, 3];
const squaredNumbers = numbers.map(num => num * num);
console.log(squaredNumbers); // [1, 4, 9]

Allows parameters to have default values if no argument or undefined is passed.

function sayHello(name = "Guest") {
console.log(`Hello, ${name}!`);
}
sayHello(); // Hello, Guest!
sayHello("Alice"); // Hello, Alice!

Collects all remaining arguments passed to a function into an array.

function sumAll(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(sumAll(1, 2, 3)); // 6
console.log(sumAll(10, 20, 30, 40)); // 100

Generator Functions (ES6): See dedicated section.

Events are actions or occurrences that happen in the browser, such as a user clicking a button, a page finishing loading, or a key being pressed. JavaScript allows you to respond to these events.

The modern and recommended way to handle events is using the addEventListener() method. This allows you to attach multiple event handlers to an element for the same event type.

Syntax: element.addEventListener(type, listener, options?)

  • type: A string representing the event type (e.g., "click", "mouseover", "keydown").
  • listener: The function (event handler) to be called when the event occurs. It receives an Event object as an argument.
  • options (optional): An object with options like capture (boolean), once (boolean), passive (boolean).
<!DOCTYPE html>
<html>
<head><title>Event Example</title></head>
<body>
<button id="myButton">Click Me</button>
<p id="message"></p>
<script>
const button = document.getElementById('myButton');
const messagePara = document.getElementById('message');
button.addEventListener('click', function(event) {
messagePara.textContent = 'Button clicked! Event type: ' + event.type;
console.log('Event object:', event);
});
button.addEventListener('mouseover', () => {
button.style.backgroundColor = 'lightblue';
});
button.addEventListener('mouseout', () => {
button.style.backgroundColor = ''; // Reset background
});
</script>
</body>
</html>
  • Mouse Events: click, dblclick, mousedown, mouseup, mousemove, mouseover, mouseout, mouseenter, mouseleave.
  • Keyboard Events: keydown, keyup, keypress (legacy, avoid if possible).
  • Form Events: submit, reset, change (for input fields, select, textarea), input, focus, blur.
  • Document/Window Events: load, unload, DOMContentLoaded, resize, scroll.

Legacy Event Handling (Avoid in new code):

Section titled “Legacy Event Handling (Avoid in new code):”
  • HTML on-event attributes: <button onclick="myFunction()">. This mixes HTML and JavaScript, making code harder to maintain.

  • DOM element on-event properties: element.onclick = myFunction;. This only allows one handler per event type.

When an event occurs, an Event object (or a more specific type like MouseEvent, KeyboardEvent) is passed to the event handler function. This object contains information about the event, such as:

  • type: The type of event.
  • target: The DOM element that triggered the event.
  • currentTarget: The DOM element to which the event handler is attached.
  • preventDefault(): Method to cancel the browser’s default action for the event (e.g., prevent form submission).
  • stopPropagation(): Method to stop the event from bubbling up or capturing down the DOM tree.

For a list of HTML5 standard events, refer to MDN: https://developer.mozilla.org/en-US/docs/Web/Events

Cookies are small text files stored on a user’s computer by their web browser, used to remember information about the user across sessions. JavaScript can interact with cookies using document.cookie.

Key operations:

  • Setting/Updating: document.cookie = "name=value; expires=UTCString; path=/; SameSite=Lax";
  • Reading: document.cookie returns a string of all cookies; you need to parse it.
  • Deleting: Set the expires attribute to a past date.

Important: Always use encodeURIComponent() for cookie values and decodeURIComponent() when reading them. Consider HttpOnly, Secure, and SameSite attributes for security (often set server-side). For client-side storage not needing server interaction, localStorage and sessionStorage are often better alternatives.

Refer to the dedicated ‘ES6 - Cookies’ section for detailed examples and best practices.

JavaScript can redirect the browser to a new URL using the window.location object.

  • window.location.href = "new_url"; (Navigates and adds to history)
  • window.location.assign("new_url"); (Same as above)
  • window.location.replace("new_url"); (Navigates but replaces current entry in history, back button won’t go to original page)
  • window.location.reload(); (Reloads current page)

For SEO, server-side redirects (301 for permanent) are generally preferred over JavaScript redirects.

Refer to the dedicated ‘ES6 - Page Redirection’ section for more details.

JavaScript provides built-in functions for simple user interactions via dialog boxes. While functional, they are modal (block user interaction with the rest of the page) and generally have a dated appearance. Modern web applications often use custom-styled modals or notifications.

Displays a simple message with an OK button.

Displays a message with OK and Cancel buttons. Returns true if OK is clicked, false if Cancel is clicked.

Displays a message asking for user input, with an input field. Returns the entered string if OK is clicked, or null if Cancel is clicked. defaultValue is an optional initial value for the input field.

alert("This is an alert!");
const wantsToContinue = confirm("Do you want to continue?");
if (wantsToContinue) {
console.log("User wants to continue.");
} else {
console.log("User does not want to continue.");
}
const userName = prompt("Please enter your name:", "John Doe");
if (userName !== null) {
console.log(`Hello, ${userName}`);
} else {
console.log("User cancelled the prompt.");
}

The void operator evaluates an expression and then returns undefined. Its primary use in the past was with javascript: URLs to prevent the browser from navigating away from the current page when an expression’s return value might otherwise cause it to.

Syntax: void expression or void(expression)

<a href="javascript:void(0);">Do nothing link</a>
<a href="javascript:void(console.log('Clicked!'));">Log and do nothing link</a>

In modern JavaScript, void 0 is sometimes used as a concise way to get the undefined value. However, simply using the undefined primitive is usually clearer. With modern event handling (e.g., event.preventDefault()), the need for javascript:void(0) in links has diminished.

JavaScript can trigger the browser’s print dialog using the window.print() method. This will attempt to print the current document.

<!DOCTYPE html>
<html>
<head><title>Print Example</title></head>
<body>
<p>This is some content to print.</p>
<button onclick="window.print()">Print this page</button>
</body>
</html>

You can use CSS media queries (@media print) to define specific styles for the printed version of your page, different from the screen version.

Objects are collections of key-value pairs (properties). ES6 introduced several enhancements for working with objects.

  • Shorthand Property Names: If a variable name is the same as the property key, you can omit the colon and value: let name = "Alice"; let person = { name }; is equivalent to let person = { name: name };
  • Shorthand Method Names: let person = { greet() { console.log("Hello"); } }; instead of let person = { greet: function() { console.log("Hello"); } };
  • Computed Property Names: Use expressions in square brackets for property keys: let propName = "age"; let person = { [propName]: 30 };

Copies enumerable own properties from one or more source objects to a target object (shallow copy). Useful for merging objects or cloning.

Object Destructuring: See dedicated section.

Refer to the dedicated ‘ES6 - Objects’ section for more details and examples.

ES6 added new properties and methods to the Number object.

  • Number.EPSILON: Smallest interval between two representable numbers.
  • Number.isFinite(value): Checks if a value is a finite number.
  • Number.isInteger(value): Checks if a value is an integer.
  • Number.isNaN(value): Checks if a value is NaN (more robust than global isNaN()).
  • Number.isSafeInteger(value): Checks if a value is a safe integer (can be exactly represented as an IEEE-754 double precision number).
  • Number.parseFloat(string) and Number.parseInt(string, radix): Global functions also available on Number object.

Prefix 0b or 0B for binary numbers (e.g., 0b1010 is 10). Prefix 0o or 0O for octal numbers (e.g., 0o12 is 10).

The Boolean object represents truth values: true or false. Values that are implicitly false (falsy values) in JavaScript include false, 0, -0, 0n (BigInt zero), "" (empty string), null, undefined, and NaN. All other values are truthy.

Strings represent textual data. ES6 introduced Template Literals and new string methods.

Template Literals: Hello, ${name}! for easy interpolation and multiline strings.

New Methods: startsWith(), endsWith(), includes(), repeat().

Refer to the dedicated ‘ES6 - Strings’ and ‘ES6 - New String Methods’ sections for details.

Arrays are ordered collections of values. ES6 added many useful methods and features for arrays.

  • Array.from(arrayLikeOrIterable, mapFn?, thisArg?): Creates a new array instance from an array-like or iterable object.
  • Array.of(...elements): Creates a new array instance with a variable number of arguments, regardless of number or type of the arguments.
  • find(callbackFn, thisArg?): Returns the first element that satisfies the provided testing function.
  • findIndex(callbackFn, thisArg?): Returns the index of the first element that satisfies the provided testing function.
  • fill(value, start?, end?): Fills all elements of an array from a start index to an end index with a static value.
  • copyWithin(target, start?, end?): Shallow copies part of an array to another location in the same array.
  • entries(): Returns a new Array Iterator object that contains key/value pairs for each index.
  • keys(): Returns a new Array Iterator object that contains the keys (indices) for each index.
  • values(): Returns a new Array Iterator object that contains the values for each index.

Spread Syntax (...) and Destructuring: Also very useful with arrays.

The Date object is used for working with dates and times. Its API has remained largely unchanged in ES6, but it’s important for date manipulation. Modern JavaScript often uses libraries like date-fns or Luxon for more robust and developer-friendly date/time handling due to complexities with time zones and formatting with the native Date object.

The Math object provides properties and methods for mathematical constants and functions. ES6 added several new helper methods:

  • Math.trunc(x): Returns the integer part of x by removing fractional digits.
  • Math.sign(x): Returns the sign of x (1 for positive, -1 for negative, 0 for zero).
  • Math.cbrt(x): Returns the cube root of x.
  • Math.log2(x): Returns the base-2 logarithm of x.
  • Math.log10(x): Returns the base-10 logarithm of x.
  • Math.log1p(x): Returns the natural logarithm of 1 + x.
  • Math.expm1(x): Returns e^x - 1.
  • Math.cosh(x), Math.sinh(x), Math.tanh(x), Math.acosh(x), Math.asinh(x), Math.atanh(x): Hyperbolic functions.
  • Math.hypot(...values): Returns the square root of the sum of squares of its arguments.
  • Math.clz32(x): Returns the number of leading zero bits in the 32-bit binary representation of x.

Regular expressions are patterns used to match character combinations in strings. ES6 introduced new flags and features:

  • y (sticky) flag: Matches only from the index indicated by the lastIndex property of the RegExp. The match must start at lastIndex.
  • u (unicode) flag: Enables more complete Unicode support, including matching characters outside the Basic Multilingual Plane (BMP) correctly and handling Unicode property escapes (\p{...}).
  • RegExp constructor can take another RegExp object as an argument: new RegExp(/abc/ig, 'i') creates a new RegExp with potentially different flags.

The Document Object Model (DOM) is a programming interface for HTML and XML documents. It represents the page structure as a tree of objects, allowing JavaScript to dynamically access and update the content, structure, and style of a web page.

  • Nodes: Everything in an HTML document is a node (element nodes, text nodes, attribute nodes, comment nodes).
  • document object: The entry point to the DOM, representing the entire HTML document.
  • Selecting Elements: - document.getElementById('id') - document.getElementsByTagName('tagname') (returns HTMLCollection) - document.getElementsByClassName('classname') (returns HTMLCollection) - document.querySelector('cssSelector') (returns the first matching element) - document.querySelectorAll('cssSelector') (returns a NodeList of all matching elements)
  • Manipulating Elements: - Reading/modifying content: element.innerHTML, element.textContent, element.value (for form elements). - Modifying attributes: element.getAttribute(), element.setAttribute(), element.removeAttribute(), direct property access (e.g., element.id, element.className). - Modifying styles: element.style.property (e.g., element.style.color = 'blue'), element.classList (add, remove, toggle, contains).
  • Creating and Adding Elements: - document.createElement('tagname') - parentNode.appendChild(newNode) - parentNode.insertBefore(newNode, referenceNode) - element.remove() (ES6+)
  • Traversing the DOM: parentNode, childNodes, firstChild, lastChild, nextSibling, previousSibling, parentElement, children, firstElementChild, lastElementChild, nextElementSibling, previousElementSibling.

Avoid using outdated methods like document.write() for modifying content after the page has loaded.

ES6 introduced new built-in iterable data structures: Map, Set, WeakMap, and WeakSet.

Ordered collection of key-value pairs. Keys can be any value (including objects and primitives). Methods: set(key, value), get(key), has(key), delete(key), clear(), size property. Iterable via keys(), values(), entries().

Ordered collection of unique values. Values can be any type. Methods: add(value), has(value), delete(value), clear(), size property. Iterable via keys(), values(), entries() (keys and values are the same for Sets).

Specialized versions where keys (for WeakMap) or values (for WeakSet) must be objects. They hold “weak” references, meaning if an object key/value is the only reference remaining, it can be garbage collected. They are not iterable and don’t have a size property. Useful for associating data with objects without preventing their garbage collection.

ES6 introduced a class syntax, which is primarily syntactic sugar over JavaScript’s existing prototype-based inheritance. It provides a cleaner and more familiar way to create objects and implement inheritance.

  • class keyword: class MyClass { ... }
  • constructor method: Special method for creating and initializing an object created with a class. There can be only one constructor per class.
  • Methods: Functions defined within a class.
  • static methods: Called on the class itself, not on instances. static myStaticMethod() { ... }
  • extends keyword: For inheritance. class ChildClass extends ParentClass { ... }
  • super keyword: Used to call the parent class’s constructor (super()) or methods (super.parentMethod()).
  • Getters and Setters: get myProp() { ... }, set myProp(value) { ... }
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // Call parent constructor
this.breed = breed;
}
speak() {
super.speak(); // Call parent method
console.log(`${this.name} barks.`);
}
}
const myDog = new Dog("Rex", "German Shepherd");
myDog.speak();
// Output:
// Rex makes a noise.
// Rex barks.

Promises are objects representing the eventual completion (or failure) of an asynchronous operation and its resulting value. They provide a cleaner way to handle asynchronous code than traditional callbacks, avoiding “callback hell”.

  • Pending: Initial state, neither fulfilled nor rejected.
  • Fulfilled (Resolved): The operation completed successfully, with a resulting value.
  • Rejected: The operation failed, with a reason (error).
const myPromise = new Promise((resolve, reject) => {
// Asynchronous operation
setTimeout(() => {
const success = true; // or false
if (success) {
resolve("Operation successful!");
} else {
reject(new Error("Operation failed."));
}
}, 1000);
});

Using .then() for fulfillment, .catch() for rejection, and .finally() for code that runs regardless of outcome.

myPromise
.then(result => {
console.log("Success:", result);
})
.catch(error => {
console.error("Error:", error.message);
})
.finally(() => {
console.log("Promise settled.");
});

async functions and the await keyword build on top of promises, providing a more synchronous-looking way to write asynchronous code.

async function fetchData() {
try {
console.log("Fetching data...");
const result = await myPromise; // Pauses execution until myPromise settles
console.log("Data received:", result);
return result;
} catch (error) {
console.error("Fetch error:", error.message);
throw error; // Re-throw if needed
}
}
fetchData().then(data => console.log("Final result from async function:", data));

ES6 introduced a standardized module system for JavaScript, allowing code to be organized into reusable pieces. Modules help manage dependencies and create more maintainable applications.

Exporting: Use the export keyword to make functions, variables, or classes available from a module.

lib.js
export const PI = 3.14159;
export function greet(name) {
return `Hello, ${name}`;
}
export default function multiply(a, b) { // Default export
return a * b;
}

Importing: Use the import keyword to use exported members in another module.

main.js
import multiply, { PI, greet } from './lib.js'; // Default import first, then named
// import * as utils from './lib.js'; // Import all as namespace
console.log(PI); // 3.14159
console.log(greet("ES6 Modules")); // Hello, ES6 Modules
console.log(multiply(5, 2)); // 10

ES6 modules are typically used in browsers via <script type="module" src="..."></script>. Node.js also supports ES modules (often requiring .mjs extension or specific package.json configuration). For older environments, transpilers like Babel convert ES modules to other formats (like CommonJS or AMD).

Proper error handling is crucial for robust applications. JavaScript uses try...catch...finally blocks for synchronous error handling, and promises have built-in mechanisms (.catch(), async/await with try/catch) for asynchronous errors.

The try block contains code that might throw an error. If an error occurs, the catch block is executed with an error object. The finally block (optional) executes regardless of whether an error occurred or not.

try {
let result = riskyOperation();
console.log(result);
} catch (error) {
console.error("An error occurred:", error.name, error.message);
// error.stack might also be useful for debugging
} finally {
console.log("Cleanup code runs here.");
}

throw statement: Used to create and throw custom errors or re-throw existing ones. throw new Error("Something went wrong");

Error Objects: Standard built-in error types include Error, SyntaxError, TypeError, RangeError, ReferenceError, URIError. You can create custom error classes by extending Error.

Refer to the dedicated ‘ES6 - Error Handling’ section for more details.

Form validation ensures that user input is correct, complete, and in the proper format before processing or submitting it. Validation can occur client-side (in the browser using JavaScript) and/or server-side.

  • Improved User Experience: Provides immediate feedback to users, reducing frustration.
  • Reduced Server Load: Prevents unnecessary requests with invalid data.
  • HTML5 Built-in Validation: Use attributes like required, type (e.g., email, number, url), pattern (for regex), min, max, minlength, maxlength on form elements. The browser handles basic validation and provides default error messages.
  • JavaScript Validation: For more complex or custom validation logic. Access form field values, check them against rules, and display custom error messages. Often used in conjunction with HTML5 validation.
<!DOCTYPE html>
<html>
<head><title>Validation</title></head>
<body>
<form id="myForm">
<label for="email">Email:</label>
<input type="text" id="email" name="email">
<span id="emailError" style="color:red;"></span><br><br>
<button type="submit">Submit</button>
</form>
<script>
const form = document.getElementById('myForm');
const emailInput = document.getElementById('email');
const emailError = document.getElementById('emailError');
form.addEventListener('submit', function(event) {
event.preventDefault(); // Prevent default form submission
validateEmail();
});
function validateEmail() {
const emailValue = emailInput.value.trim();
if (emailValue === '') {
emailError.textContent = 'Email is required.';
return false;
} else if (!/^\S+@\S+\.\S+$/.test(emailValue)) { // Simple email regex
emailError.textContent = 'Please enter a valid email address.';
return false;
}
emailError.textContent = ''; // Clear error
// If valid, you might proceed with form submission (e.g., using Fetch API)
console.log('Form submitted with email:', emailValue);
return true;
}
</script>
</body>
</html>

Important: Always implement server-side validation as well, because client-side validation can be bypassed.

JavaScript can be used to create animations on web pages by dynamically changing element properties (like position, size, color, opacity) over time.

This is the modern, preferred way to create smooth and efficient animations in JavaScript. The browser calls your callback function just before the next screen repaint (typically 60 times per second). This synchronizes animations with the browser’s refresh rate, leading to better performance and less jank compared to setTimeout or setInterval for animations.

Example: Moving an element with requestAnimationFrame

Section titled “Example: Moving an element with requestAnimationFrame”
<!DOCTYPE html>
<html>
<head>
<title>Animation</title>
<style> #box { width: 50px; height: 50px; background-color: blue; position: relative; } </style>
</head>
<body>
<div id="box"></div>
<script>
const box = document.getElementById('box');
let position = 0;
let startTime = null;
function animate(timestamp) {
if (!startTime) startTime = timestamp;
const progress = timestamp - startTime;
position += 1; // Move 1 pixel per frame
if (position > 300) position = 0; // Reset position
box.style.left = position + 'px';
if (progress < 5000) { // Run animation for ~5 seconds
requestAnimationFrame(animate);
}
}
requestAnimationFrame(animate); // Start the animation
</script>
</body>
</html>

Legacy Animation with setTimeout / setInterval:

Section titled “Legacy Animation with setTimeout / setInterval:”

While possible, using setTimeout or setInterval for animations can lead to stuttering and inefficiency because they are not synchronized with the browser’s repaint cycle. requestAnimationFrame is generally superior.

For many common animations (e.g., hover effects, transitions between states), CSS Animations and CSS Transitions are often a better choice. They are typically more performant as the browser can optimize them, and they keep presentational logic out of JavaScript.

Modern web browsers support multimedia content primarily through the HTML5 <audio> and <video> elements. JavaScript provides APIs to control these elements.

These elements allow you to embed audio and video content directly into your web pages. They have attributes like src, controls, autoplay, loop, muted, poster (for video).

<video id="myVideo" width="320" height="240" controls>
<source src="movie.mp4" type="video/mp4">
<source src="movie.ogg" type="video/ogg">
Your browser does not support the video tag.
</video>
<audio id="myAudio" controls>
<source src="sound.mp3" type="audio/mpeg">
<source src="sound.ogg" type="audio/ogg">
Your browser does not support the audio element.
</audio>

You can control playback, volume, track selection, etc., using JavaScript methods and properties on the audio/video DOM elements:

  • Methods: play(), pause(), load().
  • Properties: currentTime, duration, volume, muted, paused, ended, src.
  • Events: play, pause, ended, timeupdate, volumechange, canplay, error.
<!DOCTYPE html><html><head><title>Media Control</title></head><body>
<video id="sampleVideo" width="320" height="240" src="your_video.mp4"></video><br>
<button onclick="document.getElementById('sampleVideo').play()">Play</button>
<button onclick="document.getElementById('sampleVideo').pause()">Pause</button>
<input type="range" min="0" max="1" step="0.1" value="1"
oninput="document.getElementById('sampleVideo').volume = this.value">
Volume
</body></html>

The navigator.plugins and navigator.mimeTypes objects, previously used for detecting browser plugins (like Flash), are largely obsolete as modern web relies on built-in browser capabilities for multimedia.

Debugging is the process of finding and fixing errors (bugs) in your code. Modern browsers and Node.js provide powerful debugging tools.

All major browsers include developer tools (usually opened with F12 or right-click -> Inspect). Key features for JavaScript debugging:

  • Console: View console.log() messages, errors, and warnings. Execute JavaScript expressions interactively.
  • Debugger/Sources Panel: Set breakpoints in your code to pause execution. Step through code line-by-line (step over, step into, step out). Inspect variable values, call stacks, and scope chains.
  • Network Panel: Inspect network requests and responses.
  • Performance Panel: Profile JavaScript execution to identify bottlenecks.
  • console.log(...data): General output.
  • console.error(...data): Output an error message.
  • console.warn(...data): Output a warning message.
  • console.info(...data): Output an informational message.
  • console.table(data): Display tabular data as a table.
  • console.group(label) / console.groupEnd(): Group related log messages.
  • console.time(label) / console.timeEnd(label): Measure execution time.

Placing the debugger; statement in your code will act like a breakpoint if developer tools are open, pausing execution at that line.

  • Built-in Debugger: node inspect myscript.js (or node --inspect myscript.js for Chrome DevTools integration).
  • IDE Debuggers: VS Code and other IDEs have excellent built-in debuggers for Node.js applications.
  • Understand the error: Read error messages carefully; they often point to the problem’s location and type.
  • Reproduce the bug consistently: Identify the steps to trigger the bug.
  • Isolate the problem: Simplify the code or comment out sections to narrow down where the bug occurs.
  • Use console.log strategically: Print variable values at different stages to understand the code flow and state.
  • Use breakpoints and step through code: Observe the execution flow and variable changes in detail.

Client-side image maps allow you to define clickable areas (hotspots) within an image, where each area can link to a different URL or trigger a JavaScript function.

  • <img usemap="#mapname">: The <img> tag includes the usemap attribute, which points to the name of a <map> element.
  • <map name="mapname">: This element contains the definitions of the clickable areas.
  • <area shape="rect|circle|poly" coords="..." href="url" alt="text">: Defines a clickable area. - shape: rect (rectangle), circle, or poly (polygon). - coords: Coordinates defining the shape. (e.g., x1,y1,x2,y2 for rect; x,y,radius for circle; x1,y1,x2,y2,...,xn,yn for poly). - href: The URL to navigate to. - alt: Alternative text for the area.

You can attach JavaScript event handlers (like onclick, onmouseover) to <area> elements to perform actions instead of or in addition to navigating to a URL.

<!DOCTYPE html>
<html>
<head><title>Image Map</title>
<script>
function showRegion(regionName) {
document.getElementById('regionInfo').textContent = 'You are over: ' + regionName;
}
function clearRegion() {
document.getElementById('regionInfo').textContent = '';
}
</script>
</head>
<body>
<img src="your-image.jpg" alt="Sample Image Map" usemap="#samplemap" width="300" height="200">
<map name="samplemap">
<area shape="rect" coords="0,0,100,100" href="#" alt="Top-Left Quadrant"
onmouseover="showRegion('Top-Left Quadrant')" onmouseout="clearRegion()"
onclick="alert('Clicked Top-Left'); return false;">
<area shape="circle" coords="200,100,50" href="#" alt="Center-Right Circle"
onmouseover="showRegion('Center-Right Circle')" onmouseout="clearRegion()"
onclick="alert('Clicked Center-Right'); return false;">
</map>
<p id="regionInfo"></p>
</body>
</html>

While still supported, image maps are less common for complex UIs today. CSS techniques, SVG, or JavaScript-based hit detection on canvas might offer more flexibility for interactive graphics. However, for simple linked regions on a static image, they remain a valid option.

Understanding the browser environment is important for web development. The navigator object in JavaScript provides information about the browser and its capabilities.

  • navigator.userAgent: A string containing the user agent header sent by the browser to the server. This string typically includes browser name, version, OS, and rendering engine details. Caution: User agent sniffing is generally discouraged for feature detection as it can be unreliable and hard to maintain. Prefer feature detection.
  • navigator.language / navigator.languages: Information about the user’s preferred language(s).
  • navigator.platform: (Deprecated) A string representing the platform the browser is running on (e.g., “Win32”, “MacIntel”).
  • navigator.cookieEnabled: A boolean indicating whether cookies are enabled in the browser.
  • navigator.onLine: A boolean indicating whether the browser currently has network connectivity.
  • navigator.javaEnabled(): (Largely obsolete) Checks if Java (not JavaScript) is enabled.
  • navigator.sendBeacon(url, data?): Asynchronously transfers small amounts of HTTP data from the browser to a web server, useful for analytics or diagnostics without delaying page unload.

Instead of trying to identify the specific browser (navigator.userAgent sniffing), it’s almost always better to detect if a specific feature you want to use is supported.

if (typeof Promise !== "undefined") {
console.log("Promises are supported.");
} else {
console.log("Promises are not supported. Consider a polyfill.");
}
if ('geolocation' in navigator) {
console.log("Geolocation API is available.");
navigator.geolocation.getCurrentPosition(pos => console.log(pos.coords));
} else {
console.log("Geolocation API is not available.");
}

Modern browsers are highly standards-compliant, reducing the need for extensive browser-specific code. However, understanding browser differences can still be important for performance optimizations, handling specific browser bugs, or when using very new features.