We are still cooking the magic in the way!
Introduction to JavaScript & How It Works
What Is JavaScript?
JavaScript is the programming language of the web. While HTML provides the structure of a web page and CSS controls its visual presentation, JavaScript brings pages to life by adding interactivity, logic, and dynamic behavior. Every time you see a dropdown menu open, a form validate your input before submission, a map update in real time, or an infinite scroll load more content as you reach the bottom of a page, JavaScript is doing the work behind the scenes.
JavaScript is not just limited to browsers anymore. Thanks to environments like Node.js, JavaScript can also run on servers, build desktop applications, create mobile apps, and even control hardware devices. It is one of the most versatile and widely-used programming languages in the world, consistently ranking at or near the top of developer surveys.
Despite its name, JavaScript has nothing to do with Java. The name was a marketing decision made in the mid-1990s when Java was extremely popular. JavaScript is its own distinct language with its own syntax, rules, and ecosystem.
A Brief History of JavaScript
Understanding where JavaScript came from helps you appreciate why it works the way it does today. Here are the key milestones:
- 1995 -- Birth at Netscape: Brendan Eich created JavaScript in just 10 days while working at Netscape Communications. It was originally called Mocha, then renamed to LiveScript, and finally to JavaScript. The goal was to give web designers a lightweight scripting language to add interactivity to web pages without needing to write Java applets.
- 1997 -- ECMAScript Standard: To prevent browser wars from fragmenting the language, JavaScript was submitted to ECMA International for standardization. The official specification was named ECMAScript (ES). This ensured that all browsers would implement the same core language features.
- 2005 -- The AJAX Revolution: The introduction of AJAX (Asynchronous JavaScript and XML) allowed web pages to fetch data from servers without reloading. This was the foundation for modern single-page applications. Google Maps and Gmail demonstrated the power of this approach.
- 2009 -- Node.js: Ryan Dahl created Node.js, which allowed JavaScript to run outside the browser on servers. This was a game-changer because developers could now use a single language for both frontend and backend development.
- 2015 -- ES6 (ECMAScript 2015): This was the biggest update to JavaScript in its history. ES6 introduced classes, arrow functions, template literals, let/const, destructuring, modules, promises, and much more. Modern JavaScript is built on ES6 and its subsequent yearly updates.
- 2016-Present -- Yearly Updates: Since ES6, the language receives annual updates (ES2016, ES2017, ES2018, and so on), each adding new features and improvements. The language continues to evolve rapidly.
How Browsers Execute JavaScript
To truly understand JavaScript, you need to know what happens when a browser encounters your code. Let us walk through the process step by step.
Every modern browser contains a JavaScript engine -- a specialized program that reads, interprets, and executes JavaScript code. Here is how the execution flow works:
- Parsing: The engine reads your JavaScript code character by character and converts it into an Abstract Syntax Tree (AST) -- a structured representation of your code that the engine can understand. If there are syntax errors, the engine will throw an error at this stage.
- Compilation: Modern engines use a technique called Just-In-Time (JIT) compilation. Instead of interpreting code line by line (which is slow) or compiling everything upfront (which causes a delay before execution), JIT compilation compiles code to machine code at runtime, optimizing frequently executed code paths for maximum performance.
- Execution: The compiled machine code runs on your computer's processor. The engine manages memory allocation, garbage collection (cleaning up unused memory), and the call stack (tracking which function is currently running).
JavaScript Engines: V8, SpiderMonkey, and More
Different browsers use different JavaScript engines, but they all implement the same ECMAScript standard:
- V8 -- Developed by Google, used in Chrome, Edge, Opera, and Node.js. It is known for its exceptional performance thanks to advanced JIT compilation techniques. V8 compiles JavaScript directly to native machine code before executing it.
- SpiderMonkey -- Developed by Mozilla, used in Firefox. It was the very first JavaScript engine ever created (by Brendan Eich himself). SpiderMonkey also uses JIT compilation and continues to be actively developed.
- JavaScriptCore (Nitro) -- Developed by Apple, used in Safari and all iOS browsers. It is optimized for Apple's hardware and operating systems.
- Chakra -- Was developed by Microsoft for the old Edge browser. The new Edge browser switched to using V8 (same as Chrome) in 2020.
Adding JavaScript to a Web Page
There are three ways to include JavaScript in an HTML page: inline scripts, internal scripts, and external scripts. Let us examine each approach and understand when to use them.
1. Inline JavaScript
Inline JavaScript is written directly inside HTML attributes, typically in event handler attributes like onclick, onmouseover, or onsubmit. This approach mixes JavaScript directly with your HTML markup.
Example: Inline JavaScript in an HTML Attribute
<button onclick="alert('Hello! You clicked the button.')">
Click Me
</button>
<input type="text" onfocus="this.style.backgroundColor='lightyellow'">
<a href="#" onmouseover="this.style.color='red'">Hover over me</a>
2. Internal JavaScript (Embedded Script)
Internal JavaScript is placed inside a <script> tag within your HTML file. This is better than inline JavaScript because it separates the logic from individual elements, but the JavaScript code still lives inside the HTML file.
Example: Internal JavaScript with the Script Tag
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Internal JavaScript Example</title>
</head>
<body>
<h1 id="greeting">Hello!</h1>
<button id="changeBtn">Change Greeting</button>
<script>
// This JavaScript code is embedded in the HTML file
const button = document.getElementById('changeBtn');
const heading = document.getElementById('greeting');
button.addEventListener('click', function() {
heading.textContent = 'Welcome to JavaScript!';
heading.style.color = 'darkblue';
});
</script>
</body>
</html>
3. External JavaScript (Recommended)
External JavaScript is written in a separate .js file and linked to the HTML page using the src attribute of the <script> tag. This is the best practice and the approach you should use in all real projects.
Example: Linking an External JavaScript File
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>External JavaScript Example</title>
</head>
<body>
<h1 id="greeting">Hello!</h1>
<button id="changeBtn">Change Greeting</button>
<script src="js/main.js"></script>
</body>
</html>
Example: The External JavaScript File (js/main.js)
// js/main.js -- Separate JavaScript file
const button = document.getElementById('changeBtn');
const heading = document.getElementById('greeting');
button.addEventListener('click', function() {
heading.textContent = 'Welcome to JavaScript!';
heading.style.color = 'darkblue';
});
console.log('main.js has loaded successfully!');
The benefits of external JavaScript files include:
- Separation of Concerns: HTML handles structure, CSS handles presentation, and JavaScript handles behavior -- each in their own files.
- Reusability: The same JavaScript file can be linked to multiple HTML pages.
- Caching: Browsers cache external JavaScript files, so returning visitors do not need to download them again.
- Maintainability: It is much easier to find and fix bugs when your code is organized into separate files.
- Team Collaboration: Different developers can work on HTML templates and JavaScript logic independently without merge conflicts.
The Script Tag: Placement, defer, and async
Where you place the <script> tag in your HTML document matters significantly. It affects when and how your JavaScript code loads and executes relative to the rest of the page.
Script at the Bottom of Body (Traditional Approach)
Placing the <script> tag just before the closing </body> tag ensures that all HTML content is parsed and rendered before the JavaScript runs. This was the traditional recommendation before defer and async attributes existed.
Example: Script at the Bottom
<body>
<h1>My Page Content</h1>
<p>All HTML loads first...</p>
<!-- JavaScript loads and executes after all HTML is parsed -->
<script src="js/main.js"></script>
</body>
The defer Attribute (Modern Best Practice)
The defer attribute tells the browser to download the JavaScript file in the background while continuing to parse the HTML. The script will only execute after the entire HTML document has been completely parsed. This is the modern best practice.
Example: Using the defer Attribute
<head>
<meta charset="UTF-8">
<title>Using defer</title>
<!-- Script downloads in parallel with HTML parsing -->
<!-- Executes only after HTML is fully parsed -->
<script src="js/main.js" defer></script>
</head>
<body>
<h1>Content loads without waiting for JS</h1>
</body>
Key characteristics of defer:
- The script downloads in parallel with HTML parsing (non-blocking).
- The script executes only after the HTML document is fully parsed.
- Multiple deferred scripts execute in the order they appear in the HTML.
- It only works with external scripts (the
srcattribute must be present).
The async Attribute
The async attribute also downloads the script in the background, but it executes the script immediately as soon as it finishes downloading -- regardless of whether the HTML parsing is complete.
Example: Using the async Attribute
<head>
<!-- Script downloads in parallel, executes as soon as it finishes -->
<!-- Does NOT wait for HTML parsing to complete -->
<script src="js/analytics.js" async></script>
<script src="js/ads.js" async></script>
</head>
Key characteristics of async:
- The script downloads in parallel with HTML parsing (non-blocking).
- The script executes immediately when the download completes, pausing HTML parsing.
- Multiple async scripts do NOT guarantee execution order -- whichever finishes downloading first runs first.
- Best suited for independent scripts that do not depend on the DOM or other scripts, such as analytics or advertising trackers.
defer for scripts that need to interact with the DOM or depend on other scripts. Use async for independent scripts like analytics or ad trackers that do not depend on page content. When in doubt, use defer.The Console: Your JavaScript Playground
The browser console is the most important tool for learning and debugging JavaScript. It allows you to write and execute JavaScript code in real time, see the output of your programs, and inspect errors.
Opening the Console
To open the browser developer tools and access the console:
- Chrome / Edge: Press
F12orCtrl+Shift+J(Windows/Linux) /Cmd+Option+J(Mac). - Firefox: Press
F12orCtrl+Shift+K. - Safari: Enable the Develop menu in Preferences first, then press
Cmd+Option+C.
Using console.log()
The console.log() method is the most commonly used tool for displaying output and debugging your code. It prints values to the browser console.
Example: Using console.log() for Output
// Print a simple message
console.log('Hello, JavaScript!');
// Print numbers
console.log(42);
console.log(3.14);
// Print the result of an expression
console.log(10 + 20); // Output: 30
console.log('Age: ' + 25); // Output: Age: 25
// Print multiple values at once
console.log('Name:', 'Alice', 'Age:', 30);
// Print objects and arrays
console.log({ name: 'Alice', age: 30 });
console.log([1, 2, 3, 4, 5]);
Other Console Methods
Beyond console.log(), there are several other useful console methods:
Example: Additional Console Methods
// Warning messages (shown with yellow background)
console.warn('This is a warning message!');
// Error messages (shown with red background)
console.error('Something went wrong!');
// Informational messages
console.info('Page loaded successfully.');
// Tabular data display (great for arrays and objects)
console.table([
{ name: 'Alice', age: 30 },
{ name: 'Bob', age: 25 },
{ name: 'Charlie', age: 35 }
]);
// Timing operations (measure how long code takes)
console.time('loop');
for (let i = 0; i < 1000000; i++) {
// some operation
}
console.timeEnd('loop'); // Output: loop: 2.345ms
// Group related messages
console.group('User Details');
console.log('Name: Alice');
console.log('Age: 30');
console.log('Role: Developer');
console.groupEnd();
// Clear the console
console.clear();
console.table() when working with arrays of objects. It displays data in a beautifully formatted table that is much easier to read than the default output. Use console.time() and console.timeEnd() to measure the performance of your code.Writing Your First JavaScript Programs
Now that you understand the theory, let us write some actual JavaScript programs. We will start simple and progressively build up complexity.
Program 1: Hello World
// The classic first program in any language
console.log('Hello, World!');
// You can also display a popup dialog
alert('Hello, World!');
// Or write directly to the HTML document
document.write('<h1>Hello, World!</h1>');
document.write() in real projects. If called after the page has loaded, it will overwrite the entire page content. We use it here only for demonstration. Use console.log() for debugging output and DOM manipulation methods (which you will learn later) for updating page content.Program 2: Basic Arithmetic
// JavaScript can perform mathematical operations
console.log('Addition: ' + (5 + 3)); // 8
console.log('Subtraction: ' + (10 - 4)); // 6
console.log('Multiplication: ' + (6 * 7)); // 42
console.log('Division: ' + (20 / 4)); // 5
console.log('Remainder: ' + (17 % 5)); // 2 (modulo)
console.log('Power: ' + (2 ** 10)); // 1024 (exponentiation)
Program 3: Working with User Input
// prompt() displays a dialog box asking the user for input
let userName = prompt('What is your name?');
let userAge = prompt('How old are you?');
// Display the results
console.log('Name: ' + userName);
console.log('Age: ' + userAge);
// Create a greeting message
alert('Hello, ' + userName + '! You are ' + userAge + ' years old.');
Program 4: Simple Decision Making
let age = prompt('Enter your age:');
if (age >= 18) {
console.log('You are an adult.');
alert('Welcome! You have full access.');
} else {
console.log('You are a minor.');
alert('Welcome! Some content may be restricted.');
}
JavaScript Comments
Comments are notes you write in your code that the JavaScript engine completely ignores. They are essential for explaining your logic, leaving reminders, and making your code readable for yourself and other developers.
Example: Single-Line and Multi-Line Comments
// This is a single-line comment
// Everything after // on the same line is ignored
console.log('This runs'); // You can also put comments at the end of a line
/*
This is a multi-line comment.
Everything between the opening and closing markers is ignored.
Use this for longer explanations or temporarily disabling code.
*/
/*
console.log('This line will NOT run');
console.log('Neither will this one');
*/
// Good comment: explains WHY, not WHAT
// Calculate the discount: 20% off for orders over $100
let discount = orderTotal > 100 ? orderTotal * 0.20 : 0;
// Bad comment: just repeats what the code already says
// Set x to 5
let x = 5;
Strict Mode
JavaScript was designed to be forgiving of mistakes, which sometimes means bugs go unnoticed. Strict mode is a way to opt into a stricter version of JavaScript that catches common coding mistakes and throws errors that would otherwise be silently ignored.
Example: Enabling Strict Mode
// Enable strict mode for the entire file
// This MUST be the very first statement in the file
'use strict';
// Without strict mode, this would silently create a global variable
// With strict mode, this throws a ReferenceError
myVariable = 10; // ERROR: myVariable is not defined
// Without strict mode, assigning to a read-only property is silently ignored
// With strict mode, this throws a TypeError
undefined = 5; // ERROR: Cannot assign to undefined
NaN = 10; // ERROR: Cannot assign to NaN
Example: Strict Mode in a Function Scope
// You can also enable strict mode for individual functions
function strictFunction() {
'use strict';
// Strict mode rules apply only inside this function
let x = 10;
y = 20; // ERROR: y is not defined
}
function normalFunction() {
// Normal (sloppy) mode -- no strict enforcement
z = 30; // This silently creates a global variable (bad practice!)
}
What strict mode catches:
- Using a variable without declaring it (prevents accidental globals).
- Assigning values to read-only properties or non-writable globals.
- Deleting variables, functions, or function arguments.
- Duplicate parameter names in functions.
- Using octal number literals (like
010). - Using the
withstatement.
import and export), strict mode is automatically enabled. You do not need to add 'use strict' manually. However, when writing scripts that are not modules, it is a good practice to always include it at the top of your files.How JavaScript Interacts with HTML and CSS
JavaScript communicates with your web page through the Document Object Model (DOM). The DOM is a tree-like representation of your HTML document that JavaScript can read from and write to. Every HTML element becomes a node in this tree, and JavaScript can access, modify, add, or remove any node.
Example: JavaScript Interacting with the DOM
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DOM Interaction</title>
<style>
.highlight {
background-color: yellow;
padding: 10px;
border-radius: 5px;
}
</style>
</head>
<body>
<h1 id="title">Original Title</h1>
<p id="description">This is the original description.</p>
<button id="updateBtn">Update Content</button>
<script>
// Select elements from the DOM
const title = document.getElementById('title');
const description = document.getElementById('description');
const button = document.getElementById('updateBtn');
// Add an event listener to the button
button.addEventListener('click', function() {
// Modify the text content
title.textContent = 'Updated Title!';
description.textContent = 'JavaScript just changed this text.';
// Modify the CSS class
title.classList.add('highlight');
// Modify inline styles
description.style.color = 'darkgreen';
description.style.fontWeight = 'bold';
});
</script>
</body>
</html>
Understanding the Execution Order
JavaScript code executes synchronously by default, meaning it runs one line at a time from top to bottom. Each line must finish before the next one begins. This is an important concept to understand early.
Example: Synchronous Execution
console.log('Step 1: Start');
console.log('Step 2: Processing');
console.log('Step 3: Done');
// Output (always in this order):
// Step 1: Start
// Step 2: Processing
// Step 3: Done
// JavaScript waits for each line to complete before moving to the next
let result = 5 + 10; // This runs first
console.log(result); // Then this: 15
let doubled = result * 2; // Then this
console.log(doubled); // Finally this: 30
Common Beginner Mistakes to Avoid
Here are the most common mistakes that new JavaScript developers make. Being aware of them now will save you hours of debugging later:
- Case sensitivity: JavaScript is case-sensitive.
myVariable,myvariable, andMyVariableare three completely different identifiers. Similarly,console.log()works, butConsole.Log()does not. - Missing semicolons: While JavaScript has automatic semicolon insertion (ASI), relying on it can lead to subtle bugs. It is a good practice to always end your statements with semicolons.
- Using = instead of == or ===: A single
=is the assignment operator. Use===(strict equality) for comparisons. - Misspelling variable names: If you declare
let userNamebut later writeconsole.log(username), you will get a ReferenceError. - Forgetting to save: You edited your JavaScript file but forgot to save before refreshing the browser. Always save your files before testing.
Example: Common Mistakes and Corrections
// MISTAKE: Case sensitivity
Console.log('hello'); // ERROR: Console is not defined
console.Log('hello'); // ERROR: console.Log is not a function
console.log('hello'); // CORRECT
// MISTAKE: Assignment vs comparison
let x = 5;
if (x = 10) { // BUG: This assigns 10 to x, always true!
console.log('This always runs');
}
if (x === 10) { // CORRECT: This compares x to 10
console.log('x is 10');
}
// MISTAKE: Misspelled variable
let firstName = 'Alice';
console.log(firstname); // ERROR: firstname is not defined (capital N missing)
console.log(firstName); // CORRECT
Practice Exercise 1: Console Exploration
Open any website in your browser and open the developer console (F12, then click the Console tab). Try the following exercises directly in the console:
- Type
console.log('My name is [your name]')and press Enter. - Type
2 + 2and press Enter. Notice the console evaluates the expression. - Type
document.titleto see the title of the current page. - Type
document.body.style.backgroundColor = 'lightblue'to change the page background color. - Type
console.table([{a: 1, b: 2}, {a: 3, b: 4}])to see tabular output.
Practice Exercise 2: Your First JavaScript Page
Create a new HTML file called js-intro.html and a JavaScript file called app.js. In your HTML file, add the basic HTML5 structure, a heading that says "My First JavaScript Page," a paragraph with your name, and a button that says "Click Me." Link your JavaScript file using the <script> tag with the defer attribute in the <head>. In your app.js file, use 'use strict'; at the top, add console.log() to print "JavaScript file loaded!" and then add an event listener on the button that changes the heading text to "JavaScript is awesome!" and changes the paragraph color to blue when clicked. Open the file in your browser, check the console for your log message, and test the button.
Practice Exercise 3: Script Loading Experiment
Create three separate JavaScript files: script1.js, script2.js, and script3.js. In each file, add a console.log() that prints "Script 1 loaded", "Script 2 loaded", and "Script 3 loaded" respectively. Create an HTML file and link all three scripts in the <head> section. First, load them without any attributes and check the console order. Then add defer to all three and verify they still execute in order. Finally, change them all to async and reload the page multiple times -- notice that the execution order may change because async scripts run as soon as they download.