Modern JavaScript Tutorial
Learn modern JavaScript development from the basics to advanced concepts. This comprehensive tutorial covers JavaScript fundamentals, ES6, DOM manipulation, and more.
Introduction to Modern JavaScript Development
Welcome to your journey into the world of modern JavaScript development! This chapter serves as your initial step towards becoming proficient in JavaScript, often referred to as a “JavaScript ninja.” This material is adapted from a comprehensive course designed to guide you from the very basics of JavaScript to more advanced concepts.
Course Overview and Learning Path
This series of lessons provides a substantial free introduction to JavaScript, encompassing the first six chapters of a larger course. You will learn foundational JavaScript concepts, progressing through topics such as:
- Basic JavaScript syntax
- Arrow functions
Arrow functions provide a concise syntax for writing function expressions in JavaScript. They are often used for shorter functions and have some differences in how they handle
this
compared to traditional functions. - Template strings
Template strings (or template literals) are string literals allowing embedded expressions. You can use multi-line strings and string interpolation features with them. They are enclosed by backtick (`) characters instead of double or single quotes.
- Objects
In JavaScript, an object is a collection of key-value pairs. Objects are fundamental data structures used to represent complex entities and are a cornerstone of object-oriented programming.
- And much more
This introductory section alone provides approximately six hours of content, significantly exceeding the scope of typical free JavaScript tutorials available online. Upon mastering these fundamentals, you’ll have the option to explore the complete course, which delves into advanced JavaScript topics and practical project development.
Advanced Learning and Real-World Projects
The full course expands upon these basic principles, guiding you towards “Ninja level” JavaScript skills. It emphasizes practical application by teaching you how to build real-world projects, including:
- A weather application
- A live chat room
- A mini UI component library
For those interested in continuing their JavaScript education beyond this free introduction, a discounted link to the full course is available in the video description.
Why JavaScript? An Awesome Language
Embarking on learning a new language can initially feel overwhelming due to the volume of new information. However, the approach taken here aims to make learning enjoyable and inspire continued growth. Let’s explore why JavaScript is an exceptional and powerful language to learn.
JavaScript for Web Development: Breathing Life into Websites
This course focuses on JavaScript’s role in website development. JavaScript empowers you to create dynamic and interactive experiences within web browsers.
- Enhancing Static Websites: HTML and CSS provide the structure and styling of a website, creating a static page.
HTML (HyperText Markup Language) The standard markup language for documents designed to be displayed in a web browser. HTML provides the structure and content of a webpage. CSS (Cascading Style Sheets) A style sheet language used for describing the presentation of a document written in a markup language like HTML. CSS controls the visual aspects of a webpage, such as layout, colors, and fonts.
- Adding Interactivity: With even a few lines of JavaScript code, you can transform static websites into dynamic and engaging platforms. Examples include:
- Digital clocks
- Interactive quizzes
- Animations
This capability opens up vast possibilities for website creation and is the foundational application for which JavaScript was originally designed. Learning JavaScript in this context provides a natural and progressive pathway to mastering the language.
Beyond the Browser: The Versatility of JavaScript
While initially created for browser-based interactivity, JavaScript’s capabilities have expanded dramatically. Once you are comfortable using JavaScript for front-end development, you can transition to back-end development using technologies like Node.js.
Front-end Development The part of web development that deals with the client-side, meaning everything that users see and interact with directly in their web browser. It primarily involves HTML, CSS, and JavaScript to create user interfaces and user experiences. Back-end Development The part of web development that deals with the server-side logic and databases, hidden from the user. It handles data storage, processing, and security, and provides the functionality for the front-end to work. Node.js An open-source, cross-platform JavaScript runtime environment that executes JavaScript code server-side. Node.js allows developers to use JavaScript for backend development, enabling full-stack JavaScript applications.
However, JavaScript’s reach extends far beyond web servers. Its versatility is truly remarkable:
- Mobile Applications: Develop applications for mobile devices using frameworks built on JavaScript.
- Robotics: Program robots and control their functionalities.
- Virtual Reality (VR): Create immersive virtual reality experiences.
The ability to utilize a single programming language across such diverse applications makes JavaScript an incredibly valuable and efficient skill to acquire. Its widespread applicability and rapid evolution ensure that there will always be new and exciting ways to learn and utilize JavaScript.
Getting Started: Setting Up Your Development Environment
To begin your JavaScript journey, you will need a text editor specifically designed for writing code.
Text Editor A software application used to create, modify, and edit plain text files. For coding, specialized text editors offer features like syntax highlighting, code completion, and debugging tools to enhance the development experience.
Several excellent text editors are available:
- Sublime Text
- Atom
- Notepad++ (for Windows users)
For this course, VS Code (Visual Studio Code), developed by Microsoft, will be used.
VS Code (Visual Studio Code) A free, lightweight, yet powerful source code editor developed by Microsoft. It offers built-in support for JavaScript, TypeScript, Node.js, and has a rich ecosystem of extensions to support various programming languages and development workflows.
Installing VS Code
- Visit the VS Code website: code.visualstudio.com
- Click the download button appropriate for your operating system (Windows or Mac).
- Follow the installation instructions.
Upon launching VS Code for the first time, you will typically see a welcome screen and potentially release notes.
Essential VS Code Extensions
Extensions enhance the functionality of VS Code, making JavaScript development more efficient and enjoyable.
Extensions (VS Code) Add-ons that provide additional features and capabilities to VS Code, such as support for different programming languages, debugging tools, themes, and utilities to customize and improve the development environment.
To access extensions, click the “Extensions” icon in the Activity Bar on the side of VS Code (it resembles a square icon). Three key extensions are recommended for this course:
-
Live Server: This is the most crucial extension. Live Server allows you to preview your websites in a web browser dynamically.
Live Server A VS Code extension that launches a local development server and automatically reloads your web pages in the browser whenever you save changes to your code files. This provides a real-time preview of your website as you develop it. To install:
- Search for “Live Server” in the Extensions marketplace.
- Click the “Install” button.
- Restart VS Code for the extension to activate properly.
-
Material Icon Theme: An aesthetic package that enhances the visual appearance of VS Code’s file explorer by adding distinct icons to different file types.
Aesthetic Package In the context of software, aesthetic packages are extensions or themes that primarily focus on improving the visual appearance and user interface of the software, rather than adding new functionalities. File Explorer A component in VS Code (and other operating systems or IDEs) that allows users to navigate and manage files and folders within their project workspace. To install:
- Search for “Material Icon Theme” in the Extensions marketplace.
- Click the “Install” button.
-
Monokai ++: Another aesthetic package, this extension applies the popular Monokai color theme to your code editor, providing syntax highlighting and a visually appealing coding environment.
Syntax Highlighting A feature in text editors and IDEs that displays code in different colors and fonts according to its syntax. This makes code easier to read and understand by visually distinguishing keywords, variables, comments, and other code elements. To install:
- Search for “Monokai ++” in the Extensions marketplace.
- Click the “Install” button.
While Material Icon Theme and Monokai ++ are optional visual enhancements, Live Server is highly recommended and will be used extensively throughout this course.
Understanding Local Development Servers
Let’s delve into the concept of a server and the necessity of a local development server for web development.
Server In web development, a server is a computer system that stores website files and delivers them to users upon request. It responds to requests from clients (like web browsers) over a network, providing the resources needed to display websites. Local Development Server A server that runs on your local computer (as opposed to a remote server on the internet). It simulates a web server environment for development purposes, allowing you to test and preview your websites locally before deploying them to a live web server.
The Request-Response Cycle in Web Browsing
When you visit a website, your web browser initiates a process:
- Request: You type a website address (URL) into the address bar and press Enter. This sends a request to a web server.
Request (HTTP Request) A message sent from a client (e.g., a web browser) to a server, asking the server to provide a resource or perform an action. In web browsing, this is typically an HTTP request for a webpage or other web content. Web Server A computer system that hosts websites and responds to requests from web browsers. It stores website files (HTML, CSS, JavaScript, images, etc.) and delivers them to users over the internet.
- Server Processing: The web server, a computer located elsewhere on the internet, receives the request. It identifies the files associated with the requested website.
- Response: The web server sends a response back to your browser. This response contains the HTML, CSS, and JavaScript files that constitute the website.
Response (HTTP Response) The server’s reply to a client’s request. In web browsing, this is typically an HTTP response containing the requested web content (HTML, CSS, JavaScript, images, etc.) along with status codes indicating the outcome of the request.
- Browser Rendering: Your browser receives the response and interprets the HTML, CSS, and JavaScript to display the website on your screen.
Local Servers for Development
During website development, your project files are initially stored on your local computer, not on a remote web server. To preview your website in a browser as if it were hosted online, you need to simulate the server environment locally. This is where a local development server comes into play.
- Functionality: A local development server allows your computer to act as a web server for your projects.
- Local Address: You access your website in the browser using a specific local address, typically Localhost or
127.0.0.1
.Localhost A hostname that refers to the loopback IP address
127.0.0.1
. It is used to access network services running on the same computer. In web development,localhost
is commonly used to access websites hosted on a local development server. - File Serving: When you enter this local address in your browser, your computer’s local server responds by “serving up” your website files (HTML, CSS, and JavaScript) to the browser for display.
The Live Server extension you installed in VS Code automates the process of setting up and running a local development server, simplifying website previewing during development.
Using Live Server in Action
Let’s demonstrate how to use the Live Server extension to preview an HTML page in a browser.
Setting Up a Project
- File Tree: In VS Code, navigate to the “Explorer” view (using the top-left icon). This displays your file tree, showing your project folders and files.
File Tree A hierarchical representation of files and folders in a file system, often displayed in file explorers or IDEs to help users navigate and organize their project files.
- Create a Project Folder: Create a new folder for this chapter (e.g., “chapter-one”).
- Create
index.html
: Inside the “chapter-one” folder, create a new file namedindex.html
.
Writing Basic HTML
VS Code comes with Emmet, a built-in toolkit that provides shortcuts for writing code, including HTML.
Emmet A plugin for text editors that provides shortcuts and abbreviations to write HTML, CSS, and other code quickly. It uses a concise syntax to generate code snippets, significantly speeding up the coding process. HTML Document Boilerplate The basic HTML structure that forms the foundation of every webpage. It includes essential tags like
<!DOCTYPE html>
,<html>
,<head>
, and<body>
, providing the necessary setup for a valid HTML document.
- HTML Boilerplate: In
index.html
, typedoc
and press Tab. Emmet will generate a basic HTML document boilerplate for you. - Add Content: Inside the
<body>
tags, typeh1
and press Tab. Emmet will create<h1></h1>
tags. Enter “Test” within the<h1>
tags. - Add Paragraph: Below the
<h1>
tags, typep
and press Tab. Emmet will create<p></p>
tags. Enter “Test again” within the<p>
tags.H1 Tag (Heading 1 Tag) The HTML tag
<h1>
is used to define the most important heading on a webpage. Headings are used to structure content and improve readability. P Tag (Paragraph Tag) The HTML tag<p>
is used to define a paragraph of text on a webpage. Paragraphs are used to structure and organize textual content.
Previewing with Live Server
- Right-Click: Right-click anywhere within the
index.html
file in the editor. - Open with Live Server: Select “Open with Live Server” from the context menu.
This action will launch your default web browser and display the index.html
page. You should see “Test” as a large heading and “Test again” as a paragraph.
Dynamic Updates
One of the key advantages of Live Server is its live reload feature.
- Modify
index.html
: Go back toindex.html
in VS Code. Change the text within the<p>
tags to “Updated text”. - Save: Save the file (Ctrl+S or Cmd+S).
Immediately upon saving, the browser window displaying index.html
will automatically refresh, and you will see the updated text “Updated text” without manually reloading the page.
Understanding the Address
Observe the address in your browser’s address bar. It will typically look like http://127.0.0.1:5500/chapter-one/index.html
or http://localhost:5500/chapter-one/index.html
.
127.0.0.1
is the IP address for Localhost.IP Address (Internet Protocol Address) A numerical label assigned to each device connected to a computer network that uses the Internet Protocol for communication.
127.0.0.1
is a special IP address known as the loopback address, which always refers to the current computer.:5500
is the port number. Live Server typically uses port 5500 by default.Port Number A numerical identifier that is part of a network address and helps to direct network traffic to specific processes or services running on a computer. Port numbers range from 0 to 65535.
/chapter-one/index.html
indicates the path to yourindex.html
file within your project folder.
Localhost and 127.0.0.1
are synonymous in this context, both referring to your local machine.
Synonymous Having the same or nearly the same meaning as another word or phrase in the same language. In this context,
localhost
and127.0.0.1
are interchangeable when referring to the local server address.
Course Files and GitHub Repository
For each lesson with code from Chapter 2 onwards, course files are provided to accompany the video content. These files are available on a GitHub repository.
Course Files Supplementary files provided alongside educational materials, such as code examples, project setups, or assets, to facilitate learning and allow students to follow along with the lessons. GitHub Repository (Repo) A storage location for software projects, typically used for version control and collaboration. GitHub repositories contain all project files, including code, documentation, and history of changes, managed using Git.
Accessing Course Files
- GitHub Repository Link: The link to the GitHub repository is provided with the lecture materials.
- Branch Dropdown: On the GitHub repository page, use the branch dropdown to select the specific lesson you need. Branches organize different versions or sections of the project.
Branch Dropdown (GitHub) A menu on GitHub (and other Git repository hosting platforms) that allows users to switch between different branches of a repository. Branches are used to manage different versions of the code and to work on features or fixes in isolation.
- Browse Code: Once you select a lesson branch (e.g., “lesson-14”), you can browse the code files directly on the GitHub website.
Lesson A unit of instruction or a part of a course that covers a specific topic or set of concepts. In this context, lessons correspond to video lectures and associated code files.
Downloading Course Files
You can download the course files in two ways:
- Download Zip: Click the “Clone or download” button and select “Download ZIP”. This downloads a zip file containing all the files for the selected lesson. Extract the zip file to access the files.
- Clone Repository (Git): If you are familiar with Git and GitHub, you can clone the repository to your local machine using Git commands.
Git A distributed version control system that tracks changes in files over time. Git is widely used in software development to manage source code, collaborate with teams, and revert to previous versions of code. Clone (Git) To copy a repository from a remote server (like GitHub) to your local machine using Git. Cloning creates a local working copy of the repository, including all files and commit history. Repository (Git) A storage location for software projects managed by Git. Repositories contain all project files, history of changes, and metadata.
For project-based chapters, the completed project code will also be available in the last lecture of those chapters and on GitHub.
Support and Questions
If you encounter any issues accessing the course files or have any questions, please utilize the Q&A section associated with the course. Assistance will be readily provided.
Q&A (Questions and Answers) A forum or section where students can ask questions and receive answers, often associated with online courses or learning platforms. It provides a space for interaction, clarification, and support.
This concludes the introduction to modern JavaScript development and setting up your development environment. You are now prepared to begin writing JavaScript code in the upcoming lessons.
Chapter 1: Introduction to JavaScript Fundamentals
This chapter provides a foundational understanding of JavaScript, covering essential concepts from setting up your coding environment to understanding basic data types and operations. We will begin by establishing a working environment and then progressively explore how to add JavaScript to web pages, work with variables, understand different data types, and perform operations on them.
1. Setting Up Your Development Environment
To begin writing and running JavaScript code, you need to set up a suitable development environment on your computer. This typically involves installing a code editor and a browser with developer tools.
1.1. Installing VS Code
VS Code (Visual Studio Code) is a popular and powerful code editor that provides a user-friendly interface for writing and managing code.
VS Code (Visual Studio Code): A source code editor developed by Microsoft for Windows, Linux and macOS. It includes support for debugging, embedded Git control, syntax highlighting, intelligent code completion, snippets, and code refactoring.
- Ensure you have VS Code installed on your computer. It is a recommended code editor for web development due to its extensive features and extensions.
1.2. Installing Live Server Extension
To preview your web pages directly in the browser as you code, the Live Server VS Code extension is highly beneficial.
Live Server: A VS Code extension that launches a development local server with live reload feature for static and dynamic pages. This means any changes you save in your code editor are instantly reflected in your browser without manual refresh.
- Install the Live Server extension within VS Code. This extension allows you to right-click on an HTML file and select “Open with Live Server” to view your webpage in a browser and automatically refresh it whenever you save changes to your code.
1.3. Previewing Pages in the Browser
Once Live Server is installed, you can easily preview your HTML files in the browser:
- Right-click on your HTML file in VS Code.
- Select “Open with Live Server.”
- Your webpage will open in your default browser. Any changes you make to your HTML, CSS, or JavaScript files and save will automatically update in the browser, providing instant feedback.
2. Adding JavaScript to HTML Pages
JavaScript code can be integrated into HTML documents to add interactivity and dynamic behavior to web pages. There are two primary ways to include JavaScript in HTML: internally and externally.
2.1. Internal JavaScript (Head and Body)
JavaScript code can be directly embedded within HTML files using <script>
tags. These tags can be placed in either the <head>
or <body>
sections of your HTML document.
2.1.1. Placing Scripts in the <head>
-
To add internal JavaScript, use the
<script>
tag. -
Place the
<script>
tags within the<head>
section of your HTML file, typically below the<title>
tag. -
Write your JavaScript code between the opening
<script>
and closing</script>
tags.<!DOCTYPE html> <html> <head> <title>Page Title</title> <script> // JavaScript code here alert('Hello world'); </script> </head> <body> <h1>Page Title</h1> </body> </html>
<script>
tag: An HTML tag used to embed or reference executable scripts, most commonly JavaScript, within HTML documents.alert()
function: A built-in JavaScript function that displays a pop-up box with a message to the user. -
While placing scripts in
<head>
is possible, it can sometimes lead to page loading issues. Browsers might parse and execute scripts in the<head>
before fully rendering the page content, potentially delaying the display of the webpage.
2.1.2. Placing Scripts in the <body>
(Best Practice)
-
For better page loading performance and to avoid potential issues, it is generally recommended to place
<script>
tags at the end of the<body>
section, just before the closing</body>
tag. -
This ensures that the HTML content of the page is fully loaded and rendered before the JavaScript code is executed.
<!DOCTYPE html> <html> <head> <title>Page Title</title> </head> <body> <h1>Page Title</h1> <script> // JavaScript code here alert('Hello world'); </script> </body> </html>
2.2. External JavaScript Files
For larger projects and better code organization, it is best practice to externalize JavaScript code into separate .js
files. This approach offers several advantages, including improved code maintainability, reusability, and browser caching.
2.2.1. Creating a .js
File
-
Create a new file in your project directory with a
.js
extension (e.g.,sandbox.js
). -
Write your JavaScript code directly within this file, without using
<script>
tags.// sandbox.js alert('Hello world');
2.2.2. Linking to External JavaScript Files
-
To link an external JavaScript file to your HTML document, use the
<script>
tag with thesrc
attribute. -
Place this
<script>
tag in the<body>
section, typically at the bottom, just before the closing</body>
tag. -
The
src
attribute should specify the path to your.js
file.<!DOCTYPE html> <html> <head> <title>Page Title</title> </head> <body> <h1>Page Title</h1> <script src="sandbox.js"></script> </body> </html>
src
attribute: An attribute of the<script>
tag that specifies the URL of an external script file. -
Using external JavaScript files is the preferred method for most web development projects, especially for larger amounts of JavaScript code.
3. Understanding JavaScript Syntax: Semicolons
In JavaScript, semicolons (;
) are used to terminate statements, similar to how full stops are used to end sentences in English.
Statement (in programming): A command in a programming language that instructs the computer to perform a specific action.
Semicolon (;): A character used in JavaScript to indicate the end of a statement. While often optional due to automatic semicolon insertion, explicitly using them is considered good practice for clarity and to prevent potential errors.
- A JavaScript statement is a line of code that performs an action.
- Technically, semicolons are often optional in JavaScript due to automatic semicolon insertion (ASI). ASI is a feature of the JavaScript parser that attempts to automatically insert semicolons where it thinks they are needed.
- However, relying on ASI can sometimes lead to unexpected behavior and errors, especially in more complex code.
- It is considered good practice, especially for beginners, to explicitly use semicolons at the end of each statement to ensure code clarity and avoid potential issues.
4. Using the Browser Developer Console
Modern web browsers like Google Chrome come equipped with developer tools, which are essential for debugging and testing JavaScript code. The console is a key component of these tools, providing a space to execute JavaScript code directly and log messages.
Developer Tools (DevTools): A set of web authoring and debugging tools built into most web browsers. They provide insights into the rendered page, network activity, JavaScript execution, and more.
Console (in DevTools): A feature within browser developer tools that allows developers to log messages, run JavaScript code snippets, and inspect errors. It’s a crucial tool for debugging and testing JavaScript.
4.1. Accessing the Console
- In Google Chrome, you can open the developer tools by pressing the
F12
key. - Alternatively, you can right-click on a webpage and select “Inspect” or “Inspect Element,” and then navigate to the “Console” tab.
- In Firefox, press
Ctrl + Shift + K
to directly open the console. - In Internet Explorer, press
F12
to open developer tools and then navigate to the “Console” tab.
4.2. Using the Console as a Sandbox
- The console can be used as a sandbox to test JavaScript code snippets directly in the browser environment.
- You can type JavaScript code directly into the console and press
Enter
to execute it immediately. - This is useful for quick testing of JavaScript syntax, functions, and logic without needing to modify and reload an HTML file.
4.3. Logging to the Console from JavaScript
The console.log()
function is used to output messages and values to the browser’s console from your JavaScript code.
console.log()
function: A JavaScript method used to print output to the browser’s console, primarily for debugging and logging information.
-
console.log()
is extremely helpful for debugging and understanding the flow of your JavaScript code. -
You can log various types of data, including strings, numbers, variables, and objects, to the console.
-
Multiple values can be logged in a single
console.log()
statement by separating them with commas. -
The output in the console appears in the order in which
console.log()
statements are executed in your JavaScript code.console.log(1); console.log(2);
This code will output
1
followed by2
in the console.
5. Variables and Constants: Storing Data
Variables are fundamental building blocks in JavaScript (and most programming languages) that allow you to store and manipulate data. They act as named containers for values, such as numbers, strings, or more complex data structures.
Variable (in programming): A named storage location in a computer’s memory that can hold a value. In JavaScript, variables are declared using keywords like
let
,const
, orvar
. The value stored in a variable can be changed (forlet
andvar
) or remain constant (forconst
).
5.1. Declaring Variables with let
The let
keyword is a modern way to declare variables in JavaScript.
let
keyword: A keyword in JavaScript used to declare variables that are block-scoped and can be reassigned (their value can be changed after initial assignment).
-
To declare a variable using
let
, you use the syntax:let variableName = value;
-
Variable names should be descriptive and follow naming conventions (see section 5.4 for naming constraints).
-
The value assigned to a
let
variable can be changed later in the code.let age = 25; console.log(age); // Output: 25 age = 30; // Reassigning the value of 'age' console.log(age); // Output: 30
5.2. Declaring Constants with const
The const
keyword is used to declare constants, which are variables whose values are intended to remain unchanged throughout the program’s execution.
const
keyword: A keyword in JavaScript used to declare variables whose values must remain constant after they are assigned.const
variables are also block-scoped.
-
To declare a constant, use the syntax:
const constantName = value;
-
Once a value is assigned to a
const
variable, it cannot be reassigned. Attempting to do so will result in an error. -
Use
const
for values that should not change, such as mathematical constants (like Pi) or configuration settings.const points = 100; console.log(points); // Output: 100 // points = 50; // This will cause an error: "Assignment to constant variable"
5.3. The Older var
Keyword (Historical Context)
Before let
and const
were introduced in modern JavaScript (ES6), the var
keyword was used for variable declaration.
var
keyword: An older keyword in JavaScript used to declare variables. Unlikelet
andconst
,var
variables are function-scoped, not block-scoped, which can lead to scoping issues in larger programs. Modern JavaScript development generally favorslet
andconst
.
-
var
is still valid JavaScript syntax, but it has some scoping behaviors that can be less predictable and lead to potential issues, especially in larger and more complex codebases. -
For modern JavaScript development, it is generally recommended to use
let
andconst
instead ofvar
due to their more predictable block-scoping and clearer semantics.var score = 75; console.log(score); // Output: 75
5.4. Rules for Naming Variables
When naming variables in JavaScript, there are certain rules and conventions to follow:
- No Spaces: Variable names cannot contain spaces. Use camelCase or underscores to separate words.
- Allowed Characters: Variable names can contain letters (a-z, A-Z), numbers (0-9), underscores (
_
), and dollar signs ($
). - Cannot Start with a Number: Variable names cannot begin with a number. They can start with a letter, underscore, or dollar sign.
- CamelCase Convention: For multi-word variable names, the convention is to use camelCase. This means starting with a lowercase letter and capitalizing the first letter of each subsequent word (e.g.,
myAge
,firstName
,userScore
). - Reserved Keywords: You cannot use reserved keywords as variable names. Reserved keywords are words that have special meaning in JavaScript syntax (e.g.,
let
,const
,var
,function
,if
,else
, etc.). A list of reserved keywords will be provided separately. - Meaningful Names: Choose variable names that are descriptive and clearly indicate the purpose or data they hold. This makes your code more readable and understandable for yourself and other developers.
6. Comments in JavaScript
Comments are annotations in your code that are ignored by the JavaScript interpreter. They are used to add explanations, notes, or reminders to your code, making it more understandable and maintainable.
Comment (in programming): Explanatory notes added to source code that are ignored by the compiler or interpreter. Comments are used to improve code readability and understanding for developers.
6.1. Single-Line Comments
-
Single-line comments are created using two forward slashes (
//
). -
Anything after
//
on the same line is treated as a comment and is ignored by JavaScript.// This is a single-line comment let age = 25; // This comment explains the variable declaration
6.2. Multi-Line Comments
-
Multi-line comments are created using
/*
to begin the comment and*/
to end it. -
Everything between
/*
and*/
, even across multiple lines, is treated as a comment./* This is a multi-line comment. It can span across multiple lines and is useful for longer explanations or commenting out blocks of code. */ let age = 25;
6.3. Commenting Out Code
- Comments can also be used to temporarily disable or “comment out” lines or blocks of code. This is useful for debugging or temporarily excluding certain parts of your code from execution.
- To comment out code, simply place
//
at the beginning of each line (for single lines) or enclose the block of code within/*
and*/
(for multi-line blocks).
6.4. Keyboard Shortcut for Commenting
- In VS Code (and many other code editors), you can quickly comment out selected lines of code using a keyboard shortcut:
Ctrl + /
(Windows/Linux) orCmd + /
(macOS). - Highlight the lines you want to comment out and press the shortcut. To uncomment, use the same shortcut again.
7. JavaScript Data Types
In JavaScript, data types classify the kind of values that variables can hold. JavaScript is a loosely typed or dynamically typed language, which means you do not need to explicitly declare the data type of a variable when you create it. The JavaScript engine automatically determines the data type based on the value assigned to the variable.
Data Type (in programming): A classification that specifies the kind of value a variable can hold. Common data types include numbers, strings, booleans, and objects.
Loosely Typed Language (Dynamically Typed Language): A programming language where variable types are checked during runtime (as the program is running), and variables are not explicitly declared with a specific data type. JavaScript is an example of a loosely typed language.
JavaScript has seven primitive data types and objects. The primitive data types are:
- Number: Represents numeric values, including integers and floating-point numbers.
- String: Represents textual data, enclosed in single or double quotes.
- Boolean: Represents logical values, either
true
orfalse
. - Null: Represents the intentional absence of a value.
- Undefined: Represents a variable that has been declared but has not yet been assigned a value.
- Object: Represents complex data structures that can hold collections of key-value pairs (properties) and methods (functions). Arrays, dates, and object literals are types of objects.
- Symbol: A unique and immutable primitive value often used as object properties. (Symbols are a more advanced topic and will be covered later).
7.1. Numbers
The Number data type represents numeric values in JavaScript. It includes both integers (whole numbers) and floating-point numbers (decimal numbers).
- Examples of numbers:
1
,100
,-5
,3.14
,0.5
. - JavaScript does not distinguish between integer and floating-point numbers; all numbers are represented as a single Number type.
7.2. Strings
The String data type represents sequences of characters, used for textual data. Strings are enclosed in either single quotes ('
) or double quotes ("
).
- Examples of strings:
'hello'
,"world"
,'123'
,"[email protected]"
. - Single and double quotes are generally interchangeable for defining strings in JavaScript.
7.2.1. String Concatenation
Concatenation is the process of joining strings together. In JavaScript, the +
operator is used for string concatenation.
Concatenation (in programming): The operation of joining two or more strings end-to-end to create a new, longer string.
-
You can concatenate string literals and string variables.
-
To add spaces between concatenated strings, you need to explicitly include a space character within one of the strings.
let firstName = 'Brandon'; let lastName = 'Sanderson'; let fullName = firstName + ' ' + lastName; // Concatenating with a space console.log(fullName); // Output: Brandon Sanderson
7.2.2. Character Extraction (Square Bracket Notation)
You can access individual characters within a string using square bracket notation and an index (position).
Square Bracket Notation (for strings and arrays): A syntax used to access elements within strings and arrays by specifying their index (position) inside square brackets
[]
.
-
JavaScript strings are zero-indexed, meaning the first character is at index
0
, the second at index1
, and so on.let fullName = 'Brandon Sanderson'; let firstLetter = fullName[0]; // Accessing the character at index 0 console.log(firstLetter); // Output: B let thirdLetter = fullName[2]; console.log(thirdLetter); // Output: a
7.2.3. String Properties and Methods
Strings in JavaScript are objects and have built-in properties and methods that provide useful functionalities for working with text.
Property (of an object): A characteristic or attribute of an object that holds a value. In strings,
length
is a property.
Method (of an object): A function that is associated with an object and performs an action on that object’s data. String methods like
toUpperCase()
andtoLowerCase()
are examples.
-
length
Property: Thelength
property returns the number of characters in a string.let fullName = 'Brandon Sanderson'; let stringLength = fullName.length; // Accessing the length property console.log(stringLength); // Output: 17
-
toUpperCase()
Method: ThetoUpperCase()
method converts all characters in a string to uppercase.let fullName = 'Brandon Sanderson'; let upperCaseName = fullName.toUpperCase(); // Calling the toUpperCase() method console.log(upperCaseName); // Output: BRANDON SANDERSON
-
toLowerCase()
Method: ThetoLowerCase()
method converts all characters in a string to lowercase.let fullName = 'Brandon Sanderson'; let lowerCaseName = fullName.toLowerCase(); // Calling the toLowerCase() method console.log(lowerCaseName); // Output: brandon sanderson
-
indexOf()
Method: TheindexOf()
method returns the index (position) of the first occurrence of a specified substring within a string. If the substring is not found, it returns-1
.let email = '[email protected]'; let indexAt = email.indexOf('@'); // Finding the index of '@' console.log(indexAt); // Output: 5
Argument (in programming): A value passed to a function or method when it is called. In
email.indexOf('@')
,'@'
is the argument. Sometimes used interchangeably with “parameter”. -
Important Note: String methods like
toUpperCase()
andtoLowerCase()
do not modify the original string. They return a new string with the modified characters. The original string remains unchanged. Some methods, however, do modify the original value (these are often referred to as “destructive” methods, although they don’t literally destroy the data).
7.3. Booleans
The Boolean data type represents logical values, which can be either true
or false
. Boolean values are used for decision-making and conditional logic in programming.
-
Boolean values are not strings and are not enclosed in quotes.
-
Boolean values are often the result of comparisons and logical operations.
console.log(true); // Output: true console.log(false); // Output: false
7.4. Null
The Null data type represents the intentional absence of a value. It is a value that is explicitly assigned to a variable to indicate that it has no value or that its value is not yet known.
-
null
is an assignment value. You explicitly set a variable tonull
.let age = null; // Explicitly setting 'age' to null console.log(age); // Output: null
7.5. Undefined
The Undefined data type represents a variable that has been declared but has not yet been assigned a value. When a variable is declared without an initial value, JavaScript automatically assigns it the value undefined
.
-
undefined
is typically a system-level indication of absence of value, often assigned automatically by JavaScript.let age; // Declaring 'age' without an initial value console.log(age); // Output: undefined
7.6. Objects (Introduction)
The Object data type is a complex data structure that can hold collections of key-value pairs, known as properties. Objects are fundamental to JavaScript and are used extensively to represent more complex entities and data structures.
- Objects can contain properties (data) and methods (functions).
- Arrays are a special type of object in JavaScript, designed for ordered lists of values. Other object types include dates and object literals.
- Objects will be covered in detail in a later chapter.
7.7. Arrays (Introduction)
Arrays are a type of object specifically designed to store ordered collections of items (elements). Arrays can hold elements of any data type, including numbers, strings, booleans, objects, and even other arrays.
-
Arrays are defined using square brackets
[]
. -
Elements within an array are separated by commas
,
. -
Arrays are zero-indexed, meaning the first element is at index
0
, the second at index1
, and so on.let ninjas = ['Shaun', 'Ryu', 'Chun-li']; // Array of strings let ages = [20, 25, 30]; // Array of numbers let mixedArray = ['Ken', 'Crystal', 30, 20]; // Array of mixed data types
7.7.1. Accessing Array Elements
You can access individual elements in an array using square bracket notation and their index.
let ninjas = ['Shaun', 'Ryu', 'Chun-li'];
console.log(ninjas[0]); // Output: Shaun (first element at index 0)
console.log(ninjas[2]); // Output: Chun-li (third element at index 2)
7.7.2. Overriding Array Elements
You can modify the value of an element at a specific index in an array by assigning a new value to it using square bracket notation.
let ninjas = ['Shaun', 'Ryu', 'Chun-li'];
ninjas[1] = 'Ken'; // Overriding the element at index 1
console.log(ninjas); // Output: ['Shaun', 'Ken', 'Chun-li']
7.7.3. Array Properties and Methods
Arrays, being objects, also have properties and methods.
-
length
Property: Thelength
property of an array returns the number of elements in the array.let ninjas = ['Shaun', 'Ryu', 'Chun-li']; console.log(ninjas.length); // Output: 3
-
join()
Method: Thejoin()
method converts all elements of an array into a single string, separated by a specified separator string (passed as an argument).let ninjas = ['Shaun', 'Ryu', 'Chun-li']; let joinedString = ninjas.join(','); // Joining elements with a comma console.log(joinedString); // Output: Shaun,Ryu,Chun-li let hyphenJoined = ninjas.join('-'); console.log(hyphenJoined); // Output: Shaun-Ryu-Chun-li
-
indexOf()
Method: TheindexOf()
method returns the index of the first occurrence of a specified element in an array. If the element is not found, it returns-1
.let ninjas = ['Shaun', 'Ryu', 'Chun-li']; let indexRyu = ninjas.indexOf('Ryu'); console.log(indexRyu); // Output: 1
-
concat()
Method: Theconcat()
method creates a new array by merging an array with other arrays and/or values passed as arguments. It does not modify the original array.let ninjas = ['Shaun', 'Ryu', 'Chun-li']; let newNinjas = ninjas.concat(['Ken', 'Crystal']); // Concatenating with another array console.log(newNinjas); // Output: ['Shaun', 'Ryu', 'Chun-li', 'Ken', 'Crystal']
-
push()
Method: Thepush()
method adds one or more elements to the end of an array and returns the new length of the array. This method modifies the original array (destructive method).let ninjas = ['Shaun', 'Ryu', 'Chun-li']; let newLength = ninjas.push('Ken'); // Adding 'Ken' to the end console.log(newLength); // Output: 4 (new length of the array) console.log(ninjas); // Output: ['Shaun', 'Ryu', 'Chun-li', 'Ken'] (original array modified)
-
pop()
Method: Thepop()
method removes the last element from an array and returns that removed element. This method also modifies the original array (destructive method).let ninjas = ['Shaun', 'Ryu', 'Chun-li', 'Ken']; let removedNinja = ninjas.pop(); // Removing the last element console.log(removedNinja); // Output: Ken (removed element) console.log(ninjas); // Output: ['Shaun', 'Ryu', 'Chun-li'] (original array modified)
8. Working with Strings in Detail
Strings are a fundamental data type in JavaScript, and understanding how to manipulate them is crucial for web development. We have already touched upon some string methods and properties. Let’s delve deeper into more string methods.
8.1. More String Methods
-
lastIndexOf()
Method: ThelastIndexOf()
method returns the index of the last occurrence of a specified substring within a string. If the substring is not found, it returns-1
.let email = '[email protected]'; let lastIndexN = email.lastIndexOf('n'); // Finding the last index of 'n' console.log(lastIndexN); // Output: 14
-
slice()
Method: Theslice()
method extracts a section of a string and returns it as a new string, without modifying the original string. It takes two arguments: the starting index (inclusive) and the ending index (exclusive).let email = '[email protected]'; let sliceString = email.slice(0, 10); // Extracting from index 0 to 9 console.log(sliceString); // Output: mario@then let sliceFromFive = email.slice(5); // Extracting from index 5 to the end console.log(sliceFromFive); // Output: @theninja.co.uk
-
substring()
Method: Thesubstring()
method is similar toslice()
, but it treats the arguments differently in some cases (e.g., if start index is greater than end index). It also extracts a section of a string and returns it as a new string.let email = '[email protected]'; let substringString = email.substring(4, 10); // Extracting from index 4 to 9 console.log(substringString); // Output: o@then let substringFromSeven = email.substring(7); // Extracting from index 7 to the end console.log(substringFromSeven); // Output: theninja.co.uk
-
replace()
Method: Thereplace()
method searches a string for a specified value (or regular expression) and returns a new string where the first match is replaced with a specified replacement value. It does not modify the original string.let email = '[email protected]'; let replacedString = email.replace('m', 'w'); // Replacing the first 'm' with 'w' console.log(replacedString); // Output: [email protected] let replaceN = email.replace('n', 'W'); // Replacing the first 'n' with 'W' console.log(replaceN); // Output: [email protected] (only the first 'n' is replaced)
8.2. Template Strings (Template Literals)
Template strings (also called template literals) are a modern way to create strings in JavaScript that offer enhanced features, particularly for string interpolation (embedding variables) and multi-line strings. They are defined using backticks (`
) instead of single or double quotes.
Template String (Template Literal): A type of string literal in JavaScript, defined using backticks (
`
), that allows for string interpolation (embedding expressions) and multi-line strings.
8.2.1. String Interpolation
Template strings allow you to embed variables or expressions directly within the string using the syntax ${expression}
. This is called string interpolation.
let title = 'Best reads of 2019';
let author = 'Mario';
let likes = 30;
// Concatenation (older, less readable method)
let resultConcat = 'The blog called ' + title + ' by ' + author + ' has ' + likes + ' likes';
console.log(resultConcat);
// Template String (modern, more readable method)
let resultTemplate = `The blog called ${title} by ${author} has ${likes} likes`;
console.log(resultTemplate);
8.2.2. Multi-line Strings
Template strings can span across multiple lines without requiring special characters for line breaks.
let htmlTemplate = `
<h2>${title}</h2>
<p>By ${author}</p>
<span>This blog has ${likes} likes</span>
`;
console.log(htmlTemplate);
9. Working with Numbers in Detail
Numbers are another essential data type in JavaScript. Let’s explore numerical operations and some special numerical values.
9.1. Math Operators
JavaScript supports standard mathematical operators for performing calculations on numbers:
-
Addition:
+
-
Subtraction:
-
-
Multiplication:
*
-
Division:
/
-
Exponentiation (Power):
**
-
Remainder (Modulo):
%
console.log(10 / 2); // Output: 5 (division) console.log(10 % 3); // Output: 1 (remainder of 10 divided by 3) console.log(2 ** 3); // Output: 8 (2 to the power of 3)
9.2. Order of Operations (BODMAS/PEMDAS)
JavaScript follows the standard order of operations (often remembered by acronyms like BODMAS or PEMDAS) when evaluating mathematical expressions.
-
Brackets (or Parentheses)
-
Orders (or Exponents)
-
Division and Multiplication (from left to right)
-
Addition and Subtraction (from left to right)
let result = 5 * (10 - 3) ** 2; // Using order of operations console.log(result); // Output: 245
9.3. Increment and Decrement Operators
JavaScript provides shorthand operators for incrementing (adding 1) and decrementing (subtracting 1) a variable’s value.
- Increment Operator (
++
): Adds 1 to the variable’s value.likes++;
(equivalent tolikes = likes + 1;
)
- Decrement Operator (
--
): Subtracts 1 from the variable’s value.likes--;
(equivalent tolikes = likes - 1;
)
9.4. Shorthand Assignment Operators
JavaScript offers shorthand assignment operators to perform an operation and assign the result back to the same variable in a concise way.
+=
(Add and Assign):likes += 10;
(equivalent tolikes = likes + 10;
)-=
(Subtract and Assign):likes -= 5;
(equivalent tolikes = likes - 5;
)*=
(Multiply and Assign):likes *= 2;
(equivalent tolikes = likes * 2;
)/=
(Divide and Assign):likes /= 2;
(equivalent tolikes = likes / 2;
)
9.5. NaN
(Not a Number)
NaN
(Not a Number) is a special numeric value in JavaScript that represents an invalid number. It is typically produced when a mathematical operation cannot result in a valid number.
NaN (Not a Number): A special numeric value in JavaScript that represents an invalid number. It is returned when a mathematical operation cannot produce a meaningful numeric result.
-
Examples of operations that can result in
NaN
:- Dividing a number by a string:
5 / 'hello'
- Multiplying a number by a string:
5 * 'hello'
console.log(5 / 'hello'); // Output: NaN console.log(5 * 'hello'); // Output: NaN
- Dividing a number by a string:
9.6. Number Concatenation with Strings
When you use the +
operator to concatenate a number with a string, JavaScript performs type coercion and treats the number as a string, resulting in string concatenation instead of numerical addition.
Type Coercion (Type Conversion - Implicit): The automatic or implicit conversion of values from one data type to another by the JavaScript engine during operations. For example, when using the
+
operator with a string and a number, JavaScript may coerce the number to a string.
let likes = 10;
let resultString = 'The blog has ' + likes + ' likes'; // Number concatenated with strings
console.log(resultString); // Output: The blog has 10 likes
10. Working with Booleans in Detail
Booleans are essential for controlling the flow of your programs based on conditions.
10.1. Boolean Values: true
and false
Boolean values are simply true
or false
. They are not strings and are not enclosed in quotes.
console.log(true); // Output: true
console.log(false); // Output: false
10.2. Boolean Methods: includes()
Some JavaScript methods, like the includes()
method for strings and arrays, return boolean values to indicate whether a certain condition is met.
-
includes()
for Strings: Checks if a string contains a specified substring and returnstrue
if it does,false
otherwise.let email = '[email protected]'; let includesAt = email.includes('@'); // Checking if email includes '@' console.log(includesAt); // Output: true let includesExclamation = email.includes('!'); console.log(includesExclamation); // Output: false
-
includes()
for Arrays: Checks if an array contains a specified element and returnstrue
if it does,false
otherwise.let names = ['Mario', 'Luigi', 'Toad']; let includesLuigi = names.includes('Luigi'); // Checking if array includes 'Luigi' console.log(includesLuigi); // Output: true let includesBowser = names.includes('Bowser'); console.log(includesBowser); // Output: false
10.3. Comparison Operators: Returning Booleans
Comparison operators are used to compare values and return a boolean result (true
or false
) based on the comparison.
-
Equal to (Loose Equality):
==
(Checks if values are equal, may perform type coercion) -
Not Equal to (Loose Inequality):
!=
(Checks if values are not equal, may perform type coercion) -
Equal to (Strict Equality):
===
(Checks if values are equal and of the same type, no type coercion) -
Not Equal to (Strict Inequality):
!==
(Checks if values are not equal or not of the same type, no type coercion) -
Greater Than:
>
-
Less Than:
<
-
Greater Than or Equal To:
>=
-
Less Than or Equal To:
<=
let age = 25; console.log(age == 25); // Output: true (loose equality) console.log(age == '25'); // Output: true (loose equality, type coercion) console.log(age != 30); // Output: true (loose inequality) console.log(age === 25); // Output: true (strict equality) console.log(age === '25'); // Output: false (strict equality, no type coercion) console.log(age !== '25'); // Output: true (strict inequality) console.log(age > 20); // Output: true (greater than) console.log(age < 20); // Output: false (less than) console.log(age >= 25); // Output: true (greater than or equal to) console.log(age <= 25); // Output: true (less than or equal to)
10.4. String Comparisons
Comparison operators can also be used to compare strings. String comparisons are based on lexicographical (dictionary) order, where strings are compared character by character based on their Unicode values.
-
Strings are compared alphabetically.
-
Lowercase letters are considered “greater than” uppercase letters in JavaScript string comparisons.
let name = 'Shaun'; console.log(name == 'Shaun'); // Output: true (string equality) console.log(name == 'shuan'); // Output: false (case-sensitive) console.log(name > 'Crystal'); // Output: true ('S' comes after 'C' in alphabet) console.log(name > 'crystal'); // Output: true (lowercase 's' is greater than uppercase 'c') console.log(name > 'SHAUN'); // Output: true (lowercase 's' is greater than uppercase 'S')
10.5. Loose vs. Strict Equality
- Loose Equality (
==
and!=
): Performs type coercion if the operands have different types before comparing their values. This can sometimes lead to unexpected results when comparing values of different types. - Strict Equality (
===
and!==
): Does not perform type coercion. It checks if both the values and the types of the operands are the same. Strict equality is generally recommended for more predictable and accurate comparisons, especially when type differences are significant.
11. Type Conversion (Type Coercion)
Type conversion (or type coercion) is the process of changing a value from one data type to another. JavaScript can perform type conversion both implicitly (automatically) and explicitly (manually).
11.1. Explicit Type Conversion
Explicit type conversion is when you intentionally convert a value from one type to another using built-in JavaScript functions or operators.
-
Converting to Number:
-
Number()
function: Converts a value to a number. If the value cannot be converted to a valid number, it returnsNaN
.let scoreString = '100'; let scoreNumber = Number(scoreString); // String to number console.log(scoreNumber); // Output: 100 console.log(typeof scoreNumber); // Output: number let resultString = 'hello'; let resultNumber = Number(resultString); // Invalid string to number console.log(resultNumber); // Output: NaN
-
-
Converting to String:
-
String()
function: Converts a value to a string.let myNumber = 50; let myString = String(myNumber); // Number to string console.log(myString); // Output: 50 (as a string) console.log(typeof myString); // Output: string
-
-
Converting to Boolean:
-
Boolean()
function: Converts a value to a boolean. In JavaScript, certain values are considered “truthy” (convert totrue
) and others “falsy” (convert tofalse
).-
Truthy values: Most values are truthy, including:
- Positive and negative numbers (except
0
) - Non-empty strings
- Objects
- Arrays
true
- Positive and negative numbers (except
-
Falsy values:
0
(zero)''
(empty string)null
undefined
NaN
false
let truthyValue = Boolean(100); // Truthy number console.log(truthyValue); // Output: true let falsyValueZero = Boolean(0); // Falsy number (zero) console.log(falsyValueZero); // Output: false let truthyString = Boolean('0'); // Truthy string (not empty) console.log(truthyString); // Output: true let falsyStringEmpty = Boolean(''); // Falsy empty string console.log(falsyStringEmpty); // Output: false
-
-
11.2. Implicit Type Conversion (Type Coercion)
Implicit type conversion (type coercion) happens automatically in JavaScript when the engine attempts to perform an operation on values of different types. We saw an example of this with loose equality (==
) where JavaScript might convert types before comparison. Another common example is when using the +
operator with strings and numbers, where numbers might be coerced to strings for concatenation.
Understanding both explicit and implicit type conversion is important for writing predictable and error-free JavaScript code.
This chapter has provided a comprehensive introduction to fundamental JavaScript concepts, from setting up your environment to understanding variables, data types, and basic operations. As you continue your JavaScript journey, you will build upon these foundational concepts to create more complex and interactive web applications.
Chapter: Control Flow in JavaScript: Loops and Conditionals
Introduction to Control Flow
As programs grow in complexity, the need to manage the order in which code is executed becomes crucial. Control flow mechanisms in JavaScript allow developers to dictate the sequence of operations, enabling dynamic and responsive applications. This chapter will explore two fundamental aspects of control flow: loops for repeated execution of code blocks and conditional statements for executing code based on specific conditions. Mastering these concepts is essential for writing effective and efficient JavaScript programs.
Control Flow: In programming, control flow refers to the order in which individual statements, instructions or function calls of an imperative program are executed or evaluated. It determines the path of execution through your code.
Why Control Flow Matters
Imagine needing to process each item in a list of data or perform an action only when a user is logged in. These scenarios require the ability to control which parts of the code run and when. Control flow structures provide the tools to:
- Make Decisions: Execute different code paths based on conditions (e.g., user input, data validation).
- Repeat Actions: Perform the same block of code multiple times (e.g., iterating through arrays, animations).
- Create Dynamic Logic: Build programs that adapt to different situations and inputs.
This chapter will delve into the specifics of loops and conditional statements in JavaScript, equipping you with the knowledge to effectively manage the flow of execution in your programs.
Loops: Repeating Code Blocks
Loops are fundamental control flow structures that enable the repeated execution of a block of code as long as a certain condition remains true. This is incredibly useful for tasks that involve iteration, such as processing lists of data or performing actions multiple times. JavaScript offers several types of loops, each suited to different scenarios.
Loop: In programming, a loop is a sequence of instructions that is continually repeated until a certain condition is reached. Loops automate repetitive tasks without writing the same code multiple times.
For Loops: Iterating a Known Number of Times
The for loop is a powerful and versatile loop structure in JavaScript, particularly well-suited for situations where the number of iterations is known in advance, or can be determined. It provides a concise way to initialize a counter, define a condition for loop continuation, and increment the counter in each iteration.
For Loop: A control flow statement for specifying iteration, which allows code to be executed repeatedly. It is characterized by three parts: initialization, condition, and final expression, all within the loop’s header.
Syntax of a For Loop
for (initialization; condition; finalExpression) {
// Code to be executed repeatedly
}
Let’s break down each part of the for loop syntax:
- Initialization:
let i = 0
- This statement is executed only once at the beginning of the loop. It typically declares and initializes a counter variable (often namedi
,j
, ork
). This variable tracks the current iteration of the loop.
Initialization Variable: A variable declared and assigned an initial value within the initialization part of a for loop. It acts as a counter or index to keep track of the loop’s progress.
- Condition:
i < 5
- This expression is evaluated before each iteration of the loop. If the condition evaluates totrue
, the code block inside the loop is executed. If it evaluates tofalse
, the loop terminates, and execution continues after the loop block.
Condition (in loops): An expression that is evaluated before each iteration of a loop to determine whether the loop should continue executing. The loop continues as long as the condition is true.
- Final Expression:
i++
- This expression is executed after each iteration of the code block. It is commonly used to update the counter variable, typically by incrementing or decrementing it.
Final Expression: An expression that is executed after each iteration of a for loop, usually to update the loop counter variable. It ensures that the loop condition eventually becomes false, preventing infinite loops.
- Code Block:
{ // Code to be executed repeatedly }
- This is the block of code enclosed in curly braces{}
that is executed repeatedly as long as the condition is true.
Code Block: A section of code enclosed in curly braces
{}
. It groups together a sequence of statements and is treated as a single unit, often associated with control flow structures like loops and conditionals.
Example: Simple For Loop
for (let i = 0; i < 5; i++) {
console.log("In loop: " + i);
}
console.log("Loop finished");
Explanation:
- Initialization:
let i = 0
- The counteri
is initialized to 0. - Condition Check (Iteration 1):
i < 5
(0 < 5) istrue
. - Code Block Execution (Iteration 1):
console.log("In loop: " + i);
(Outputs “In loop: 0”) - Final Expression (Iteration 1):
i++
(i
becomes 1) - Condition Check (Iteration 2):
i < 5
(1 < 5) istrue
. - Code Block Execution (Iteration 2):
console.log("In loop: " + i);
(Outputs “In loop: 1”) … and so on until … - Condition Check (Iteration 5):
i < 5
(5 < 5) isfalse
. - Loop Termination: The loop ends, and execution continues with
console.log("Loop finished");
.
Output:
In loop: 0
In loop: 1
In loop: 2
In loop: 3
In loop: 4
Loop finished
For Loops and Arrays: Iterating Through Data
For loops are particularly useful for iterating through arrays, which are ordered collections of data. By combining the for loop with array indexing, you can access and process each element of an array.
Array: An array is a data structure that stores a collection of elements, each identified by an index or key. Arrays in JavaScript are ordered and can hold elements of different data types.
const names = ["Shawn", "Muriel", "Luigi"];
for (let i = 0; i < names.length; i++) {
console.log(names[i]);
}
Explanation:
names.length
: This property of an array returns the number of elements in the array. In this case,names.length
is 3.i < names.length
: The loop continues as long as the counteri
is less than the length of thenames
array.names[i]
: This is square bracket notation used to access the element at indexi
in thenames
array.
Output:
Shawn
Muriel
Luigi
Iteration Terminology:
Iteration: In the context of loops, an iteration refers to a single execution of the loop’s code block. Each time the code inside the loop is run, it is considered one iteration.
Each cycle through the loop, executing the code block, is referred to as an iteration. In the example above, the loop iterates three times, once for each name in the names
array.
Creating HTML Dynamically within a For Loop
For loops can be used to dynamically generate HTML content based on data.
const names = ["Shawn", "Muriel", "Luigi"];
for (let i = 0; i < names.length; i++) {
let html = `<div>${names[i]}</div>`;
console.log(html);
}
Explanation:
- Template Literals (Template Strings): Backticks (
) are used to define template literals, which allow for string interpolation using
${variableName}`. This makes it easy to embed JavaScript expressions within strings.
Output:
<div>Shawn</div>
<div>Muriel</div>
<div>Luigi</div>
This example demonstrates how to create HTML snippets within each iteration of the loop, which can be further manipulated or inserted into a web page.
While Loops: Looping Based on a Condition
The while loop provides another way to create loops in JavaScript. Unlike the for loop, the while loop is primarily driven by a condition. It continues to execute its code block as long as the specified condition remains true. While loops are often used when the number of iterations is not known beforehand, but rather depends on a dynamic condition.
While Loop: A control flow statement that repeatedly executes a block of code as long as a specified condition is true. The condition is checked before each iteration.
Syntax of a While Loop
while (condition) {
// Code to be executed repeatedly
// Update condition (crucial to avoid infinite loops)
}
- Condition:
condition
- This expression is evaluated before each iteration. If it’strue
, the code block is executed. If it’sfalse
, the loop terminates. - Code Block:
{ // Code to be executed repeatedly }
- The code block to be executed repeatedly. - Condition Update (Important!): Crucially, within the code block, there must be a mechanism to update the condition, typically by modifying a variable involved in the condition. Failing to do so can result in an infinite loop.
Infinite Loop: A loop that continues to execute indefinitely because its termination condition is never met. This often results in program crashes or freezes.
Example: Simple While Loop
let i = 0; // Initialization outside the loop
while (i < 5) {
console.log("In loop: " + i);
i++; // Increment inside the loop (condition update)
}
console.log("Loop finished");
Explanation:
- Initialization (Outside Loop):
let i = 0;
- The counteri
is initialized before the while loop begins. - Condition Check (Iteration 1):
i < 5
(0 < 5) istrue
. - Code Block Execution (Iteration 1):
console.log("In loop: " + i);
(Outputs “In loop: 0”) - Condition Update (Iteration 1):
i++;
(i
becomes 1) - Condition Check (Iteration 2):
i < 5
(1 < 5) istrue
. … and so on until … - Condition Check (Iteration 5):
i < 5
(5 < 5) isfalse
. - Loop Termination: The loop ends, and execution continues with
console.log("Loop finished");
.
Output:
In loop: 0
In loop: 1
In loop: 2
In loop: 3
In loop: 4
Loop finished
Key Difference from For Loop: In a while loop, the initialization and condition update are handled separately from the loop’s condition check, typically outside and inside the code block, respectively. In contrast, the for loop encapsulates all three (initialization, condition, final expression) within its parentheses.
While Loops and Arrays: Iterating Through Data (Similar to For Loop)
While loops can also be used to iterate through arrays, similar to for loops.
const names = ["Shawn", "Muriel", "Luigi"];
let i = 0; // Initialization
while (i < names.length) {
console.log(names[i]);
i++; // Increment
}
Output:
Shawn
Muriel
Luigi
Do-While Loops: Ensuring At Least One Execution
The do-while loop is a variation of the while loop that guarantees the code block will execute at least once, regardless of the initial condition. The condition is checked after the code block is executed in each iteration.
Do-While Loop: A control flow statement similar to a while loop, but the condition is checked after the code block is executed. This ensures that the code block runs at least once.
Syntax of a Do-While Loop
do {
// Code to be executed at least once and repeatedly
// Update condition (crucial to avoid infinite loops)
} while (condition); // Semicolon required at the end
do
Block:{ // Code to be executed ... }
- The code block that will be executed at least once.while (condition);
: - The condition is checked after each execution of thedo
block. Iftrue
, the loop continues; iffalse
, the loop terminates. Note the semicolon;
at the end of thewhile
statement, which is required.
Example: Do-While Loop
let i = 5; // Initialization
do {
console.log("Value of i: " + i);
i++;
} while (i < 5);
console.log("Loop finished");
Explanation:
- Initialization:
let i = 5;
-i
is initialized to 5. do
Block Execution (Iteration 1): The code block is executed unconditionally for the first time.console.log("Value of i: " + i);
(Outputs “Value of i: 5”) andi++;
(i
becomes 6).- Condition Check (Iteration 1):
i < 5
(6 < 5) isfalse
. - Loop Termination: The loop ends after the first iteration because the condition is false.
Output:
Value of i: 5
Loop finished
Even though the initial condition i < 5
is false (since i
is 5), the code block inside the do
block executes once.
When to Use Do-While Loops: Do-while loops are useful in scenarios where you need to perform an action at least once and then conditionally repeat it based on a condition, such as prompting a user for input and then repeating the prompt until valid input is received.
Conditional Statements: Executing Code Based on Conditions
Conditional statements allow programs to make decisions and execute different code paths based on whether certain conditions are true or false. This is essential for creating dynamic and responsive programs that can adapt to various inputs and situations. The primary conditional statement in JavaScript is the if statement, often used in conjunction with else and else-if to handle multiple conditions.
Conditional Statement: A programming construct that allows a program to execute different blocks of code depending on whether a specified condition is true or false. This enables decision-making within programs.
If Statements: Executing Code When a Condition is True
The if statement is the most basic conditional statement. It executes a block of code only if a specified condition evaluates to true
.
If Statement: A fundamental conditional statement in programming that executes a block of code only if a specified condition is true.
Syntax of an If Statement
if (condition) {
// Code to be executed if the condition is true
}
- Condition:
condition
- An expression that is evaluated. If it evaluates totrue
, the code block is executed. If it evaluates tofalse
, the code block is skipped. - Code Block:
{ // Code to be executed if condition is true }
- The block of code that is executed only when the condition is true.
Example: Simple If Statement
const age = 25;
if (age > 20) {
console.log("You are over 20 years old");
}
Explanation:
- Condition Check:
age > 20
(25 > 20) istrue
. - Code Block Execution:
console.log("You are over 20 years old");
is executed.
Output:
You are over 20 years old
If age
were 15, the condition age > 20
would be false
, and the code block would not be executed, resulting in no output.
If Statements with Data: Checking Array Length
If statements can be used to check conditions related to data, such as the length of an array.
const ninjas = ["Shawn", "Rio", "Translate", "Yoshi"];
if (ninjas.length > 3) {
console.log("That's a lot of ninjas!");
}
Explanation:
ninjas.length > 3
: Checks if the length of theninjas
array (which is 4) is greater than 3. The condition istrue
.
Output:
That's a lot of ninjas!
Practical Use Case: Password Length Validation
A common use case for if statements is data validation, such as checking password length.
const password = "password123";
if (password.length >= 8) {
console.log("That password is long enough");
}
Explanation:
password.length >= 8
: Checks if the length of thepassword
string is greater than or equal to 8. The condition istrue
.
Output:
That password is long enough
Else Statements: Providing an Alternative Code Path
The else statement is used in conjunction with an if statement to provide an alternative block of code to execute when the if statement’s condition is false
.
Else Statement: Used with an if statement to specify a block of code to be executed if the if statement’s condition is false. It provides an alternative path of execution.
Syntax of If-Else Statement
if (condition) {
// Code to be executed if the condition is true
} else {
// Code to be executed if the condition is false
}
if (condition)
Block: Executed if the condition istrue
.else
Block: Executed if the condition isfalse
.
Example: If-Else Statement for Password Validation
const password = "pass";
if (password.length >= 8) {
console.log("That password is long enough");
} else {
console.log("Password is not long enough");
}
Explanation:
- Condition Check:
password.length >= 8
(“pass”.length >= 8) isfalse
. else
Block Execution: The code block within theelse
statement is executed.
Output:
Password is not long enough
Important Note: In an if-else structure, only one of the code blocks (either the if
block or the else
block) will ever be executed, never both.
Else-If Statements: Handling Multiple Conditions
The else-if statement allows you to check multiple conditions in sequence. It is used when you have more than two possible code paths and want to execute different code blocks based on different conditions.
Else-If Statement: Used in conjunction with if and else to check multiple conditions in sequence. It provides a way to handle more than two possible code paths.
Syntax of If-Else If-Else Statement
if (condition1) {
// Code to be executed if condition1 is true
} else if (condition2) {
// Code to be executed if condition1 is false and condition2 is true
} else if (condition3) {
// Code to be executed if condition1 and condition2 are false, and condition3 is true
} else {
// Code to be executed if all preceding conditions are false
}
You can have multiple else if
blocks to check as many conditions as needed. The else
block at the end is optional but provides a default code path if none of the preceding if
or else if
conditions are true.
Example: Else-If for Password Strength
const password = "password123456";
if (password.length >= 12) {
console.log("That password is mighty strong");
} else if (password.length >= 8) {
console.log("That password is strong enough");
} else {
console.log("Password is not long enough");
}
Explanation:
- Condition 1 Check:
password.length >= 12
(“password123456”.length >= 12) istrue
. if
Block Execution:console.log("That password is mighty strong");
is executed. The rest of theelse if
andelse
blocks are skipped.
Output:
That password is mighty strong
If the password length were, for example, 9, the first condition would be false, the second condition (password.length >= 8
) would be true, and the “That password is strong enough” message would be logged. If the password were shorter than 8 characters, the else
block would be executed.
Order Matters: The order of else if
conditions is important. Conditions are evaluated from top to bottom. Once a condition is found to be true, its corresponding code block is executed, and the rest of the else if
and else
blocks are skipped.
Logical Operators: Combining Conditions
Logical operators are used to combine or modify conditions within conditional statements and loops. JavaScript provides three main logical operators: AND (&&
), OR (||
), and NOT (!
).
Logical Operators: Symbols or keywords used to combine or modify boolean expressions (conditions). They allow for creating more complex conditions in control flow statements.
Logical AND (&&
): Requiring Multiple Conditions to be True
The logical AND operator (&&
) returns true
if and only if all the conditions it connects are true
. If any of the conditions are false
, the entire expression becomes false
.
Logical AND (
&&
): A binary operator that returns true if and only if both of its operands are true. In conditional statements, it allows you to require multiple conditions to be met.
Example: Logical AND for Password Strength and Special Character
const password = "Password@123456";
if (password.length >= 12 && password.includes("@")) {
console.log("That password is mighty strong");
} else if (password.length >= 8) {
console.log("That password is strong enough");
} else {
console.log("Password is not long enough");
}
Explanation:
password.length >= 12 && password.includes("@")
: This condition checks both if the password length is at least 12 AND if it includes the ”@” symbol. Both conditions must be true for the entire condition to be true.
Output:
That password is mighty strong
Logical OR (||
): Requiring At Least One Condition to be True
The logical OR operator (||
) returns true
if at least one of the conditions it connects is true
. It only returns false
if all the conditions are false
.
Logical OR (
||
): A binary operator that returns true if at least one of its operands is true. In conditional statements, it allows you to execute code if any of several conditions are met.
Example: Logical OR for Password Length or Special Character
const password = "short@";
if (password.length >= 12 && password.includes("@")) {
console.log("That password is mighty strong");
} else if (password.length >= 8 || password.includes("@")) {
console.log("That password is strong enough");
} else {
console.log("Password is not long enough");
}
Explanation:
password.length >= 8 || password.includes("@")
: This condition checks if the password length is at least 8 OR if it includes the ”@” symbol. If either of these conditions is true (or both), the entire condition is true.
Output:
That password is strong enough
Even though the password length is less than 8, the condition is true because it includes the ”@” symbol.
Logical NOT (!
): Reversing a Condition
The logical NOT operator (!
) is a unary operator (it operates on a single operand). It reverses the boolean value of its operand. If the operand is true
, !
makes it false
, and if it’s false
, !
makes it true
.
Logical NOT (
!
): A unary operator that reverses the boolean value of its operand. It is used to negate a condition, making true conditions false and vice versa.
Boolean: A data type that has one of two possible values: true or false. Boolean values are fundamental to conditional logic and decision-making in programming.
Example: Logical NOT to Check if User is Not Logged In
let isLoggedIn = false;
if (!isLoggedIn) {
console.log("You must be logged in to continue");
}
Explanation:
!isLoggedIn
:isLoggedIn
isfalse
.!isLoggedIn
reverses this totrue
. Therefore, the condition is true.
Output:
You must be logged in to continue
The logical NOT operator is particularly useful for checking for the absence of a condition or reversing the logic of an existing condition.
Control Flow Keywords within Loops: break
and continue
JavaScript provides two keywords, break
and continue
, that offer more fine-grained control over loop execution.
break
Statement: Exiting a Loop Prematurely
The break
statement is used to immediately terminate a loop, regardless of the loop’s condition. When break
is encountered inside a loop, the loop execution stops, and the program control flow moves to the statement immediately following the loop.
Break Statement: A control flow statement used to terminate the execution of a loop (for, while, do-while) or a switch statement prematurely. It immediately exits the loop or switch block.
Example: break
to Exit Loop When Top Score is Reached
const scores = [50, 75, 100, 30, 0, 10];
for (let i = 0; i < scores.length; i++) {
console.log("Score: " + scores[i]);
if (scores[i] === 100) {
console.log("Congrats! You got the top score!");
break; // Exit the loop when score is 100
}
}
Explanation:
The loop iterates through the scores
array. When it encounters a score of 100, the if
condition becomes true, the congratulatory message is logged, and the break
statement is executed. This immediately terminates the loop, and the remaining scores (30 and 0) are not processed.
Output:
Score: 50
Score: 75
Score: 100
Congrats! You got the top score!
continue
Statement: Skipping to the Next Iteration
The continue
statement is used to skip the rest of the current iteration of a loop and proceed to the next iteration. When continue
is encountered, the code block within the current iteration is immediately exited, and the loop condition is re-evaluated to begin the next iteration.
Continue Statement: A control flow statement used within loops to skip the remainder of the current iteration and proceed to the next iteration of the loop.
Example: continue
to Skip Logging Zero Scores
const scores = [50, 75, 100, 30, 0, 10];
for (let i = 0; i < scores.length; i++) {
if (scores[i] === 0) {
continue; // Skip to the next iteration if score is 0
}
console.log("Score: " + scores[i]);
}
Explanation:
When the loop encounters a score of 0, the if
condition is true, and the continue
statement is executed. This causes the loop to skip the console.log("Score: " + scores[i]);
line for that iteration and immediately proceed to the next iteration (for the score of 10). As a result, the score 0 is not logged to the console.
Output:
Score: 50
Score: 75
Score: 100
Score: 30
Score: 10
Switch Statements: Efficiently Handling Multiple Cases
Switch statements provide an alternative to long if-else-if
chains when you need to compare a single variable against multiple possible values (cases). Switch statements can make code more readable and efficient in certain situations, especially when dealing with a fixed set of possible values.
Switch Statement: A control flow statement that allows a variable to be tested for equality against a list of values (cases). It provides a more structured and often more readable alternative to long if-else-if chains when dealing with multiple possible values for a single variable.
Syntax of a Switch Statement
switch (expression) {
case value1:
// Code to execute if expression === value1
break;
case value2:
// Code to execute if expression === value2
break;
// ... more cases ...
default:
// Code to execute if expression does not match any case
break; // Optional in the default case
}
switch (expression)
: Theexpression
is evaluated once, and its value is compared against the values of eachcase
.case value1:
: Eachcase
represents a possible value that theexpression
might have. Thevalue1
is compared to theexpression
using strict equality (===
).- Code Block (under
case
): The code to be executed if theexpression
matches thecase value
. break;
: Thebreak
statement is crucial at the end of eachcase
block. It terminates the switch statement after a match is found and prevents “fall-through” to the next case.default:
: Thedefault
case is optional. It provides a block of code to be executed if theexpression
does not match any of thecase
values.
Example: Switch Statement for Grade Evaluation
const grade = "C";
switch (grade) {
case "A":
console.log("You got an A - Excellent!");
break;
case "B":
console.log("You got a B - Good job!");
break;
case "C":
console.log("You got a C - Average");
break;
case "D":
console.log("You got a D - Needs improvement");
break;
case "E":
console.log("You got an E - Failing");
break;
default:
console.log("Not a valid grade");
break;
}
Explanation:
switch (grade)
: Thegrade
variable (which is “C”) is evaluated.case "C":
: The switch statement checks ifgrade === "C"
. This is true.- Code Block Execution (Case “C”):
console.log("You got a C - Average");
is executed. break;
: Thebreak
statement terminates the switch statement.
Output:
You got a C - Average
Strict Equality in Switch Statements: Switch statements use strict equality (===
) for comparisons. This means that both the value and the data type must match for a case to be considered a match.
Strict Equality (
===
): An equality operator in JavaScript that checks if two values are equal without type coercion. It returns true only if both the value and the data type of the operands are the same.
Fall-Through (Without break
): If you omit the break
statement at the end of a case
block, the execution will “fall through” to the next case, even if the next case’s value does not match the switch expression. This is sometimes intentional but often leads to unexpected behavior if break
is unintentionally omitted.
Block Scope: Variable Visibility and Lifetime
Block scope is a crucial concept in JavaScript (introduced with let
and const
keywords) that defines the scope (visibility and accessibility) of variables declared within code blocks. Understanding block scope is essential for writing predictable and maintainable JavaScript code.
Block Level Scope: The scope of a variable that is limited to the block of code (usually defined by curly braces
{}
) in which it is declared. Variables declared withlet
andconst
have block scope.
Scope: In programming, scope refers to the region of a program where a declared variable can be accessed and used. It determines the visibility and lifetime of variables.
Global Scope vs. Block Scope
- Global Scope: Variables declared outside of any function or code block have global scope. They can be accessed from anywhere in the JavaScript file.
Global Scope: The widest scope in JavaScript. Variables declared outside of any function or block have global scope and can be accessed from anywhere within the script.
- Block Scope: Variables declared inside a code block (using
let
orconst
) have block scope. They are only accessible within that specific code block and any nested code blocks within it. They are not accessible outside of the block.
Local Scope: In the context of block scope, local scope refers to the scope of variables declared within a code block. These variables are local to that block and are not accessible from outside.
Example: Block Scope in If Statements
let age = 30; // Global scope variable
if (true) {
const age = 40; // Block scope variable (re-declaration is allowed within a block)
const name = "Shawn"; // Block scope variable
console.log("Inside first code block - Age:", age, ", Name:", name); // Accesses block scope variables
}
console.log("Outside code block - Age:", age); // Accesses global scope variable
// console.log("Outside code block - Name:", name); // Error! name is not defined (block scope)
if (true) {
console.log("Inside second code block - Age:", age); // Accesses the nearest available 'age' in scope chain (global scope in this case)
}
Explanation:
- Global
age
:let age = 30;
declares a variableage
with global scope. - Block Scope
age
andname
: Inside theif
block,const age = 40;
andconst name = "Shawn";
declare new variables with block scope. These variables are different from the globalage
. - Inside First Block:
console.log("Inside first code block ... ");
logs the block scopeage
(40) andname
(“Shawn”). - Outside Block:
console.log("Outside code block - Age:", age);
logs the global scopeage
(30), which remains unchanged. - Error (Commented Out):
console.log("Outside code block - Name:", name);
would cause an error becausename
is block-scoped and not accessible outside theif
block. - Nested Block: The second
if
block can access the global scopeage
(30) because there is noage
variable declared within its own block or any block enclosing it other than the global scope.
Nested Code Blocks: Block scope applies to nested code blocks as well. Variables declared in an outer block are accessible in inner blocks, unless a variable with the same name is re-declared in the inner block, creating a new local scope variable.
Nested Code Blocks: Code blocks that are contained within other code blocks. Block scope rules apply hierarchically, with inner blocks inheriting scope from outer blocks, unless variables are re-declared in inner blocks.
let
and const
vs. var
: The concept of block scope is a key difference between let
/const
and the older var
keyword. Variables declared with var
have function scope (scoped to the nearest function), not block scope. This means var
variables declared within blocks are still accessible outside the block, which can lead to unexpected behavior and is generally discouraged in modern JavaScript. let
and const
are preferred for their block-scoping behavior, which promotes better code organization and reduces the risk of variable scope-related errors.
Conclusion
This chapter has provided a comprehensive overview of control flow in JavaScript, focusing on loops and conditional statements. By mastering these fundamental concepts, you gain the ability to create dynamic, responsive, and efficient JavaScript programs. Understanding loops allows you to automate repetitive tasks, while conditional statements enable your programs to make decisions and adapt to different situations. Furthermore, understanding block scope is critical for managing variable visibility and avoiding common pitfalls in JavaScript development. As you continue your JavaScript journey, these control flow techniques will form the bedrock of your programming logic.
Understanding Functions in JavaScript
Introduction to Functions
Functions are a fundamental building block in JavaScript and many other programming languages. They are categorized as an object type within JavaScript’s data types.
Object Type: In JavaScript, objects are complex data types that can store collections of data and methods. Functions, arrays, and objects themselves are all considered object types. Data Type: A data type classifies the kind of value a variable can hold. JavaScript’s primitive data types include string, number, boolean, null, and undefined. Object types are more complex and include objects, arrays, and functions.
Functions allow you to encapsulate a block of code and execute it whenever needed. Think of a function as a reusable container holding a specific set of instructions.
-
Defining a Function: You define a function once, specifying the code it contains.
-
Calling (or Invoking) a Function: To execute the code within a function, you need to call or invoke it. This can be done multiple times throughout your program without rewriting the code each time.
Call/Invoke (a function): To execute or run the code contained within a function, you must “call” or “invoke” it by using its name followed by parentheses.
Analogy: Imagine a button on a webpage. Each time a user clicks this button, you want the same action to occur. You can create a function that holds the code for this action. Every button click then simply calls this function, executing the code within it, whether the button is clicked once or many times.
The Power of Reusability and Parameters
Functions promote code reusability. Instead of writing the same code multiple times, you define it once within a function and call it whenever needed.
Functions can also accept input values, known as arguments, to perform operations on them. This makes functions even more versatile.
- Passing Values (Arguments): You can pass values into a function when you call it. These values are used by the code inside the function.
- Returning Values: Functions can also produce an output or result after processing the input or performing its task. This output is called a return value.
Example: Consider converting geographic coordinates (latitude and longitude) into a street address. You could create a function that:
- Accepts latitude and longitude values as input.
- Processes these coordinates to find the corresponding address.
- Returns the street address as an output.
If you have a list of 50 coordinates, you only need to define this function once. Then, you can call it 50 times, passing in a different set of coordinates each time, and each call will return the corresponding address.
Methods: Functions Associated with Objects
The transcript mentions “methods” and briefly distinguishes them from functions.
Method: A method is essentially a function that is associated with an object or a data type. It performs an action specifically related to that object.
While methods are functions, they are invoked differently, often using dot notation on an object. We will explore methods in more detail later, especially when discussing objects in JavaScript.
Creating Your First Function: Function Declaration
Let’s learn how to create functions in JavaScript. The first way is using a function declaration.
Function Declaration: A way to define a function in JavaScript using the
function
keyword, followed by a function name, parentheses for parameters, and curly braces{}
to enclose the function’s code block.
Syntax:
function functionName() {
// Code to be executed when the function is called
}
Example from Transcript:
function greet() {
console.log("hello there");
}
Explanation:
-
function
keyword: Indicates that you are declaring a function. -
greet
: This is the name of the function. You’ll use this name to call the function later. Function names follow similar naming conventions as variables. -
()
(Parentheses): These parentheses are essential. They are used to define parameters (inputs) that the function can accept. In this example, there are no parameters, so the parentheses are empty. -
{}
(Curly Braces): These curly braces define the code block of the function. All the JavaScript code that you want to be executed when thegreet
function is called goes inside these braces.Code Block: A block of code is a group of JavaScript statements enclosed within curly braces
{}
. It defines a scope and is commonly used with functions, loops, and conditional statements.
Calling the Function:
Simply writing the function declaration does not execute the code inside. To run the code, you need to call the function.
greet(); // This line calls the greet function
This will execute the console.log("hello there");
line within the greet
function, and “hello there” will be displayed in the browser’s console.
Function Expression: Storing Functions in Variables
Another way to create functions in JavaScript is using a function expression.
Function Expression: A way to define a function by assigning an anonymous function (a function without a name) to a variable.
Syntax:
const variableName = function() {
// Code to be executed
};
Example from Transcript:
const speak = function() {
console.log("good day");
};
Explanation:
-
const speak =
: This declares a constant variable namedspeak
. We useconst
because we generally don’t want to reassign functions.Constant (const): A keyword in JavaScript used to declare variables whose values are intended to remain constant after they are assigned.
const
variables must be initialized with a value when they are declared. Variable: A named storage location in a program’s memory that can hold a value. In JavaScript, variables are declared using keywords likevar
,let
, orconst
. -
function()
: This is an anonymous function – a function without a name. The function itself is the value being assigned to thespeak
variable. -
{}
(Curly Braces): The code block of the function, just like in function declarations. -
;
(Semicolon): Function expressions, being assignment statements, usually end with a semicolon.Semicolon (;): A character used in JavaScript to separate statements. While often optional due to automatic semicolon insertion (ASI), it’s good practice to include them, especially at the end of expressions.
Calling a Function Expression:
You call a function expression using the variable name followed by parentheses.
speak(); // Calls the function stored in the 'speak' variable
Function Declaration vs. Function Expression and Hoisting
While both function declarations and expressions create functions, there’s a subtle difference related to hoisting.
Hoisting: In JavaScript, hoisting is a behavior where variable and function declarations are moved to the top of their scope before code execution. This means you can sometimes use a function or variable before it is actually declared in your code.
Function Declarations are Hoisted:
Function declarations are hoisted to the top of their scope. This means you can call a function declared using the function
keyword before its actual declaration in your code.
Example (Hoisting with Function Declaration):
greet(); // This will work even though greet is declared later
function greet() {
console.log("hello there");
}
Function Expressions are NOT Hoisted (in the same way):
Function expressions are not hoisted in the same way. While the variable declaration is hoisted, the function assignment is not. Therefore, you cannot call a function expression before its declaration.
Example (No Hoisting with Function Expression):
speak(); // This will cause an error: "speak is not defined"
const speak = function() {
console.log("good day");
};
Best Practice:
For code clarity and maintainability, it’s generally considered best practice to declare your functions (both declarations and expressions) before you call them. This makes your code easier to read and understand, avoiding potential confusion due to hoisting. Function expressions are often preferred because they encourage this good practice and provide a more consistent coding style.
Passing Values to Functions: Parameters and Arguments
Functions become much more powerful when they can accept input values. These input values are called arguments when you call the function and are received as parameters within the function definition.
Parameter: A parameter is a named variable listed inside the parentheses in the function definition. It acts as a placeholder for values that will be passed into the function when it is called. Argument: An argument is the actual value that is passed to a function when it is called. Arguments correspond to the parameters defined in the function definition.
Example from Transcript:
const speak = function(name) { // 'name' is a parameter
console.log(`good day ${name}`); // Using template string
};
speak("Mario"); // "Mario" is an argument
Explanation:
-
function(name)
: In the function definition,name
is a parameter. It acts as a variable local to the function.Local Variable: A variable that is declared inside a function or a code block and has scope only within that function or block. It cannot be accessed from outside its scope.
-
speak("Mario")
: When calling the function,"Mario"
is the argument being passed in. This argument’s value is assigned to thename
parameter inside thespeak
function.
Multiple Parameters and Arguments:
Functions can accept multiple parameters, separated by commas in both the function definition and when calling the function.
const speak = function(name, time) { // 'name' and 'time' are parameters
console.log(`good ${time} ${name}`);
};
speak("Mario", "morning"); // "Mario" and "morning" are arguments
The order of arguments is crucial. The first argument is assigned to the first parameter, the second argument to the second parameter, and so on.
Default Parameter Values:
You can set default values for parameters. If an argument is not provided when calling the function, the default value will be used.
const speak = function(name = "Luigi", time = "night") {
console.log(`good ${time} ${name}`);
};
speak(); // Output: good night Luigi (default values used)
speak("Shawn"); // Output: good night Shawn (default time used)
speak("Shawn", "day"); // Output: good day Shawn (both arguments provided)
Returning Values from Functions
Functions can not only perform actions but also produce and return values. This is done using the return
keyword.
Return Keyword: A keyword in JavaScript used within a function to specify the value that the function should output or “return” back to the point where it was called. When
return
is executed, the function’s execution stops, and the specified value is returned.
Example from Transcript:
const calcArea = function(radius) {
const area = 3.14 * radius * radius;
return area; // Returns the calculated area
};
const circleArea = calcArea(5); // Function call returns a value, stored in circleArea
console.log(circleArea); // Output: 78.5
Explanation:
return area;
: Thereturn
keyword specifies that the value of thearea
variable should be sent back as the result of thecalcArea
function.const circleArea = calcArea(5);
: WhencalcArea(5)
is called, it calculates the area and returns that value. This returned value is then assigned to thecircleArea
constant.
Benefits of Returning Values:
Returning values allows you to:
- Use the result of a function in other parts of your code.
- Chain function calls (use the output of one function as input to another).
- Create modular and reusable code.
Simplified Return (Implicit Return in Arrow Functions):
In arrow functions, if the function body consists of a single expression, you can use an implicit return. You can omit the return
keyword and the curly braces {}
.
const calcArea = (radius) => 3.14 * radius * radius; // Implicit return
const circleArea = calcArea(5);
console.log(circleArea); // Output: 78.5
Arrow Functions: A Concise Syntax
Arrow functions provide a shorter and more modern syntax for writing functions in JavaScript.
Arrow Function: A concise syntax for defining functions in JavaScript, introduced in ES6. They are often shorter and can have lexical
this
binding, which differs from traditional function expressions.
Basic Syntax:
(parameters) => {
// function body
return value; // Optional if single expression
};
Converting a Regular Function to an Arrow Function (Example from Transcript):
Regular Function:
const calcArea = function(radius) {
const area = 3.14 * radius * radius;
return area;
};
Arrow Function Equivalent (Step-by-step simplification):
-
Remove
function
keyword and add arrow=>
:const calcArea = (radius) => { const area = 3.14 * radius * radius; return area; };
-
Remove parentheses if only one parameter:
const calcArea = radius => { const area = 3.14 * radius * radius; return area; };
-
Implicit return for single expression:
const calcArea = radius => 3.14 * radius * radius; // Implicit return
Simplifications with Arrow Functions:
-
Single Parameter: Parentheses around parameters are optional if there is only one parameter.
-
Implicit Return: For functions with a single expression that is returned, you can omit the
return
keyword and curly braces. The expression’s value is automatically returned. -
No Parameters or Multiple Parameters: Parentheses are required if there are no parameters or more than one parameter:
// No parameters const greet = () => "hello world"; // Multiple parameters const add = (a, b) => a + b;
this
Keyword and Arrow Functions (Brief Mention):
The transcript briefly mentions a difference between regular functions and arrow functions related to the this
keyword. This is a more advanced topic that will be covered later. For now, understand that arrow functions have a different way of handling this
compared to regular functions, which can be important in certain situations.
this
keyword: In JavaScript,this
is a keyword that refers to the context in which a function is executed. Its value can vary depending on how a function is called, particularly in object-oriented programming and event handling.
Methods Revisited: Dot Notation
As mentioned earlier, methods are functions associated with objects or data types. Methods are invoked using dot notation.
Dot Notation: A way to access properties or methods of an object in JavaScript. It involves placing a dot (
.
) after the object or value, followed by the name of the property or method you want to access.
Example:
const message = "Hello";
const upperCaseMessage = message.toUpperCase(); // toUpperCase() is a method of the string object
console.log(upperCaseMessage); // Output: HELLO
Explanation:
message.toUpperCase()
: Here,toUpperCase()
is a method of the string objectmessage
. Dot notation (.
) is used to access and call this method.
Distinguishing Functions and Methods:
- Functions: Standalone blocks of code that are called by their name.
- Methods: Functions that are associated with an object or data type and are called using dot notation on that object or data type.
Essentially, methods are functions, but their invocation and context are different.
Callback Functions: Functions Passed as Arguments
A powerful concept in JavaScript is callback functions.
Callback Function: A function that is passed as an argument to another function. The “callback” function is intended to be executed or “called back” at a later point in time, often after an asynchronous operation is completed or in response to an event.
General Premise:
- You have a function (let’s call it
higherOrderFunction
) that accepts another function as an argument. - The function passed as an argument is the callback function.
- Inside
higherOrderFunction
, at some point, the callback function is executed (or “called back”).
Example from Transcript (Illustrative):
const myFunc = (callbackFunction) => { // Accepts a callback function
let valueToPass = "Hello from myFunc";
// ... some code ...
callbackFunction(valueToPass); // Call the callback function, passing a value
};
myFunc(function(valueReceived) { // Pass an anonymous function as a callback
console.log("Callback function called with value:", valueReceived);
});
Common Use Case: Array forEach
Method
The forEach
method is a built-in array method that iterates over each element in an array and executes a provided callback function for each element.
Array
forEach
method: A method available on JavaScript arrays that executes a provided function once for each element in the array, in ascending index order.
Example using forEach
and a Callback Function (from Transcript):
const people = ["Mario", "Luigi", "Ryu", "Shawn", "Chun-li"];
people.forEach(function(person, index) { // Callback function (regular function)
console.log(`Index: ${index}, Person: ${person}`);
});
Explanation:
people.forEach(...)
: TheforEach
method is called on thepeople
array.function(person, index) { ... }
: This is the callback function being passed as an argument toforEach
.- Callback Function Parameters:
person
: Represents the current element being processed in the array during iteration.index
: (Optional) Represents the index of the current element in the array.
forEach
Operation: For each element in thepeople
array,forEach
executes the callback function, passing the current element (person
) and its index (index
) as arguments to the callback.
Arrow Function as Callback with forEach
(Common Style):
people.forEach((person, index) => { // Arrow function callback
console.log(`Index: ${index}, Person: ${person}`);
});
Externalizing the Callback Function:
You can define the callback function separately and then pass it to forEach
(or any function that accepts a callback).
const logPerson = (person, index) => {
console.log(`Index: ${index}, Hello ${person}`);
};
people.forEach(logPerson); // Pass the logPerson function as a callback
Practical Example: Generating HTML with forEach
and Callbacks
The transcript provides a practical example of using forEach
and a callback function to dynamically generate HTML list items based on an array of names. This demonstrates how callback functions can be used to process data and manipulate the webpage content.
This example, while briefly touching on browser interaction and DOM manipulation (topics to be covered in detail later), showcases the power of callback functions in real-world JavaScript development.
DOM (Document Object Model): The Document Object Model (DOM) is a programming interface for HTML and XML documents. It represents the structure of a document as a tree of objects, where each object represents a part of the document (e.g., elements, attributes, text). JavaScript can use the DOM to access and manipulate the content, structure, and style of web pages. CSS Selector: A pattern used to select HTML elements based on their tag name, class, ID, attributes, and more. CSS selectors are used in CSS to style elements and in JavaScript (using methods like
querySelector
andquerySelectorAll
) to select elements for manipulation. Inner HTML: A property of HTML elements in the DOM that allows you to get or set the HTML content within that element.
In Summary:
Callback functions are a fundamental concept in JavaScript, enabling asynchronous programming, event handling, and creating more flexible and reusable code. They are essential for working with browser events, DOM manipulation, and many JavaScript APIs.
Chapter: Understanding Objects in JavaScript
Introduction to Objects
Welcome to the world of JavaScript objects! Objects are a fundamental concept in JavaScript and are crucial for building complex and interactive web applications. This chapter will introduce you to the core principles of objects in JavaScript, explain how to create and manipulate them, and explore their significance in the language.
To grasp the concept of objects, let’s start by drawing a parallel to real-life objects. Think about a common object like a smartphone.
Real-Life Objects vs. JavaScript Objects
Just like real-world objects, JavaScript objects have two key characteristics:
- Properties: These are the attributes or characteristics that describe the object. For a smartphone, properties might include its color, size, model, and storage capacity.
- Methods: These are the actions or behaviors that the object can perform. A smartphone can ring, take pictures, play music, and connect to the internet.
JavaScript objects mirror this structure. They too possess properties to store data and methods to perform actions.
Properties: In the context of objects, properties are characteristics or attributes that describe the object. They store data associated with the object.
Methods: In object-oriented programming, methods are functions that are associated with an object and define the actions or operations that the object can perform.
Examples of JavaScript Objects
Let’s consider some examples to illustrate this further:
-
User Object: Imagine representing a user in a web application.
- Properties:
email
,username
,age
,location
. - Methods:
login()
,logout()
. These methods would define the actions a user can take within the application.
- Properties:
-
Blog Object: Consider a blog post on a website.
- Properties:
title
,content
,author
,publicationDate
. - Methods:
publish()
,unpublish()
,delete()
. These methods would manage the lifecycle of a blog post.
- Properties:
As you can see, JavaScript objects allow us to structure data and functionality in a way that closely models real-world entities. This makes our code more organized, readable, and maintainable.
JavaScript also provides built-in objects like Date
and Math
, which offer pre-defined functionalities for common tasks. Furthermore, JavaScript empowers us to create our own custom objects to represent specific entities within our applications.
Creating Objects using Object Literal Notation
One of the simplest and most common ways to create objects in JavaScript is using object literal notation.
Object Literal Notation: A way to create objects in JavaScript using curly braces
{}
. It involves defining object properties as key-value pairs within these braces.
Object literal notation is surprisingly straightforward. Let’s explore how it works.
Syntax of Object Literal Notation
To create an object literal, you use curly braces {}
. Inside these braces, you define properties as key-value pairs.
Key-Value Pair: A fundamental structure in objects where each property is identified by a unique “key” (a string or Symbol) and associated with a “value” (any JavaScript data type).
Here’s a step-by-step breakdown:
- Declare a variable: Start by declaring a variable to hold your object.
- Assign curly braces: Assign
{}
to the variable. This signifies an object literal. - Define properties (key-value pairs): Inside the curly braces, add properties in the format
key: value
.key
: This is the name of the property (always a string, even if you don’t use quotes).value
: This is the value associated with the property. It can be any JavaScript data type (string, number, boolean, array, object, function, etc.).
- Separate properties with commas: If you have multiple properties, separate each key-value pair with a comma
,
.
Example:
let user = {
name: "Crystal",
age: 30,
email: "[email protected]",
location: "Berlin",
blogs: ["why mac-and-cheese rules", "ten things to make with Marmite"]
};
In this example:
user
is the variable holding the object.{}
defines an object literal.name: "Crystal"
,age: 30
, etc., are key-value pairs representing properties.name
,age
,email
,location
, andblogs
are the keys (property names)."Crystal"
,30
,"[email protected]"
,"Berlin"
, and["why mac-and-cheese rules", "ten things to make with Marmite"]
are the corresponding values.
Formatting for Readability:
While you can write all properties on a single line, it’s best practice to format each key-value pair on a new line for improved readability, especially for objects with many properties:
let user = {
name: "Crystal",
age: 30,
email: "[email protected]",
location: "Berlin",
blogs: [
"why mac-and-cheese rules",
"ten things to make with Marmite"
]
};
Accessing Object Properties
Once you have created an object, you need to be able to access its properties to retrieve or modify the stored data. JavaScript provides two primary ways to access object properties: dot notation and square bracket notation.
Dot Notation
Dot notation is the more common and often preferred method for accessing properties when you know the property name in advance.
Syntax:
objectName.propertyName
Example:
console.log(user.name); // Output: Crystal
console.log(user.age); // Output: 30
In these examples, user.name
accesses the name
property of the user
object, and user.age
accesses the age
property.
Square Bracket Notation
Square bracket notation provides another way to access object properties. It is particularly useful when:
- The property name is stored in a variable.
- The property name is not a valid JavaScript identifier (e.g., contains spaces or special characters).
Syntax:
objectName["propertyName"]
Example:
console.log(user["email"]); // Output: [email protected]
let propertyKey = "location";
console.log(user[propertyKey]); // Output: Berlin
In the first example, user["email"]
accesses the email
property using square bracket notation. Notice that the property name is enclosed in string quotes.
In the second example, the property name "location"
is stored in the propertyKey
variable. Square bracket notation allows us to use this variable to dynamically access the location
property.
When to use which notation:
- Dot notation: Use when you know the property name directly in your code and it’s a valid JavaScript identifier. It is generally considered cleaner and more readable.
- Square bracket notation: Use when the property name is dynamic (e.g., comes from a variable) or when the property name is not a valid JavaScript identifier.
Modifying Object Properties
You can also modify the values of existing object properties using both dot notation and square bracket notation.
Modifying with Dot Notation
Syntax:
objectName.propertyName = newValue;
Example:
user.age = 35;
console.log(user.age); // Output: 35 (age property is updated)
This code changes the value of the age
property of the user
object to 35
.
Modifying with Square Bracket Notation
Syntax:
objectName["propertyName"] = newValue;
Example:
user["name"] = "Chun-Li";
console.log(user.name); // Output: Chun-Li (name property is updated)
This code updates the name
property of the user
object to "Chun-Li"
using square bracket notation.
Adding Methods to Objects
Objects in JavaScript can not only store data through properties but also perform actions through methods. Methods are essentially functions that are associated with an object.
Defining Methods
To add a method to an object, you define a property whose value is a function. You can use a concise syntax introduced in ES6 for defining methods.
Syntax (Concise Method Syntax):
let objectName = {
propertyName: propertyValue,
methodName() {
// Method body (code to be executed when the method is called)
}
};
Example:
let user = {
name: "Crystal",
age: 30,
email: "[email protected]",
location: "Berlin",
blogs: [
"why mac-and-cheese rules",
"ten things to make with Marmite"
],
login() {
console.log('user logged in');
},
logout() {
console.log('user logged out');
},
logBlogs() {
console.log('This user has written the following blogs:');
this.blogs.forEach(blog => {
console.log(blog);
});
}
};
In this example, login
, logout
, and logBlogs
are methods of the user
object.
Calling Methods
To execute a method of an object, you use dot notation followed by parentheses ()
, just like calling a regular function.
Syntax:
objectName.methodName();
Example:
user.login(); // Output: user logged in
user.logout(); // Output: user logged out
user.logBlogs(); // Output:
// This user has written the following blogs:
// why mac-and-cheese rules
// ten things to make with Marmite
The this
Keyword in Methods
The this
keyword is crucial when working with methods inside objects.
this
Keyword: In JavaScript,this
is a special keyword that refers to the context in which the current code is being executed. In the context of an object method,this
refers to the object itself.
Within a method, this
refers to the object on which the method is called. This allows methods to access and manipulate the object’s properties.
In the logBlogs
method example:
logBlogs() {
console.log('This user has written the following blogs:');
this.blogs.forEach(blog => {
console.log(blog);
});
}
this.blogs
inside the logBlogs
method correctly accesses the blogs
property of the user
object. this
in this context points to the user
object because the logBlogs
method is called on the user
object (user.logBlogs()
).
Important Note about Arrow Functions and this
:
If you define a method using an arrow function, the behavior of this
is different. Arrow functions do not have their own this
context. They inherit the this
value from the surrounding (lexical) scope. In the context of object methods, this can lead to this
not referring to the object itself if you use an arrow function.
Example (Avoid Arrow Functions for Methods when using this
):
let user = {
name: "Crystal",
blogs: ["blog1", "blog2"],
logBlogs: () => { // Arrow function - 'this' will NOT refer to 'user'
console.log(this.blogs); // 'this' will likely be the global object (window in browsers)
}
};
user.logBlogs(); // Might result in an error or unexpected output
For methods that need to access object properties using this
, it’s recommended to use the regular function syntax (as shown in the initial login
, logout
, and logBlogs
examples) or the concise method syntax, which both ensure this
correctly refers to the object.
Objects within Arrays
Just as arrays can hold various data types, they can also contain objects as elements. This is a powerful combination for structuring complex data.
Example: Array of Blog Objects:
const blogs = [
{ title: 'Why mac-and-cheese rules', likes: 30 },
{ title: 'ten things to make with Marmite', likes: 50 }
];
Here, blogs
is an array where each element is an object representing a blog post. Each blog object has title
and likes
properties.
Accessing Properties of Objects within Arrays:
To access properties of objects inside an array, you combine array indexing and object property access (dot or square bracket notation).
Example:
console.log(blogs[0].title); // Output: Why mac-and-cheese rules (title of the first blog)
console.log(blogs[1]["likes"]); // Output: 50 (likes of the second blog)
When iterating through an array of objects, you can access object properties within the loop.
Example (Iterating through blogs
array):
blogs.forEach(blog => {
console.log(blog.title, blog.likes);
});
// Output:
// Why mac-and-cheese rules 30
// ten things to make with Marmite 50
Built-in JavaScript Objects: The Math
Object
JavaScript provides several built-in objects that offer pre-defined functionalities. One such object is the Math
object.
Built-in Objects: Objects that are part of the JavaScript language itself, providing pre-defined properties and methods for common tasks.
The Math
object provides properties for mathematical constants and methods for performing mathematical operations.
Accessing the Math
Object:
You access the Math
object directly using Math
(with a capital ‘M’).
Example (Logging the Math
object):
console.log(Math);
This will output the Math
object to the console, showing its properties and methods.
Math
Object Properties (Constants)
The Math
object has properties that represent mathematical constants:
Math.PI
: Represents the mathematical constant Pi (π).Math.E
: Represents Euler’s number (e).
Example (Using Math.PI
and Math.E
):
console.log(Math.PI); // Output: 3.141592653589793
console.log(Math.E); // Output: 2.718281828459045
Math
Object Methods (Functions)
The Math
object also includes various methods for mathematical operations:
Math.round(x)
: Roundsx
to the nearest integer.Math.floor(x)
: Returns the largest integer less than or equal tox
(rounds down).Math.ceil(x)
: Returns the smallest integer greater than or equal tox
(rounds up).Math.trunc(x)
: Returns the integer part ofx
by removing any fractional digits (truncates).Math.random()
: Returns a pseudo-random floating-point number between 0 (inclusive) and 1 (exclusive).
Example (Using Math
methods):
let area = 7.7;
console.log(Math.round(area)); // Output: 8
console.log(Math.floor(area)); // Output: 7
console.log(Math.ceil(area)); // Output: 8
console.log(Math.trunc(area)); // Output: 7
console.log(Math.random()); // Output: A random number between 0 and 1 (e.g., 0.4567...)
console.log(Math.round(Math.random() * 100)); // Output: A random integer between 0 and 100 (inclusive)
The Math.random()
method is particularly useful for generating random numbers in various applications, such as games or simulations.
Primitive vs. Reference Types
In JavaScript, data types are categorized into two main groups: primitive types and reference types. Understanding the difference between them is crucial for comprehending how JavaScript handles data in memory and how variables behave.
Primitive Types
Primitive Types: Basic data types in JavaScript that represent simple values directly. They are immutable, meaning their values cannot be changed directly.
JavaScript’s primitive types are:
- Number: Represents numeric values (integers and floating-point numbers).
- String: Represents textual data.
- Boolean: Represents logical values (
true
orfalse
). - Null: Represents the intentional absence of a value.
- Undefined: Represents a variable that has been declared but not assigned a value.
- Symbol: (Introduced in ES6) Represents unique and immutable identifiers.
Reference Types (Object Type)
Reference Types: Data types in JavaScript that are objects. They store references to memory locations where the actual object data is stored. They are mutable, meaning their properties can be changed.
All objects in JavaScript, including:
- Object Literals (
{}
) - Arrays (
[]
) - Functions
- Dates
- Built-in Objects (like
Math
)
are considered reference types.
Memory Storage: Stack vs. Heap
The distinction between primitive and reference types is related to how they are stored in computer memory:
-
Stack: Primitive values are stored directly on the stack. The stack is a memory region that is fast to access but has limited space. When you assign a primitive value to a variable, the actual value is stored on the stack, and the variable name is directly associated with that value.
-
Heap: Reference types (objects) are stored on the heap. The heap is a larger memory region that can hold more complex data but is slightly slower to access than the stack. When you create an object and assign it to a variable, the object itself is stored on the heap, and the variable on the stack stores a pointer (reference) to the object’s location in the heap.
Implications of Primitive vs. Reference Types
The way primitive and reference types are stored in memory has significant implications for variable assignment and copying:
1. Copying Primitive Values:
When you copy a primitive value from one variable to another, you create a copy of the actual value. Changes to one variable do not affect the other.
Example (Primitive Types - Independent Copies):
let score1 = 50;
let score2 = score1; // score2 gets a copy of the value 50
console.log(score1, score2); // Output: 50 50
score1 = 100; // Changing score1
console.log(score1, score2); // Output: 100 50 (score2 remains unchanged)
2. Copying Reference Values:
When you copy a reference type (object) from one variable to another, you are copying the pointer (reference), not the actual object itself. Both variables will now point to the same object in memory. Changes made through one variable will be reflected when accessing the object through the other variable.
Example (Reference Types - Shared Reference):
const user1 = { name: 'Ryu', age: 30 };
const user2 = user1; // user2 gets a copy of the pointer to the same object
console.log(user1, user2); // Output: { name: 'Ryu', age: 30 } { name: 'Ryu', age: 30 }
user1.age = 40; // Changing a property of the object through user1
console.log(user1, user2); // Output: { name: 'Ryu', age: 40 } { name: 'Ryu', age: 40 } (user2 also reflects the change)
user2.name = 'Chun-Li'; // Changing a property through user2
console.log(user1, user2); // Output: { name: 'Chun-Li', age: 40 } { name: 'Chun-Li', age: 40 } (user1 also reflects the change)
This behavior is important to understand to avoid unexpected side effects when working with objects and arrays in JavaScript. If you need to create a truly independent copy of an object (not just a reference), you need to use techniques like object cloning or deep copying, which will be discussed in more advanced chapters.
Conclusion
This chapter has provided a comprehensive introduction to objects in JavaScript. You have learned:
- What objects are and how they relate to real-world objects.
- How to create objects using object literal notation.
- How to access and modify object properties using dot and square bracket notation.
- How to add methods to objects and use the
this
keyword. - How objects can be stored within arrays.
- About built-in objects like the
Math
object. - The crucial distinction between primitive and reference types and its implications for memory storage and variable behavior.
With this foundational knowledge, you are well-equipped to start working with objects in JavaScript and build more structured and dynamic applications. In the following chapters, we will delve deeper into object-oriented programming concepts and explore more advanced object manipulation techniques.
Chapter: Introduction to Dynamic Web Pages with JavaScript and the Document Object Model (DOM)
Introduction: Moving Beyond Static Web Pages
Welcome to a new phase in our JavaScript journey! Having mastered the fundamentals of JavaScript, we’re now ready to explore its exciting applications in web browsers. JavaScript’s original purpose was to bring interactivity to web pages, and that’s precisely what we’ll be focusing on in this chapter and beyond.
We’re going to move past simply displaying static content. Get ready to learn how to:
- Dynamically add content to a webpage using JavaScript.
- Modify the styling of web page elements in real-time.
- React to user interactions, such as clicks and mouse movements, making your web pages responsive and engaging.
- Even create interactive elements like pop-up boxes.
This chapter marks a significant step towards building truly dynamic and user-friendly web experiences. Our central focus will be the Document Object Model, or DOM.
Document Object Model (DOM): The 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. The DOM represents the document as a tree of objects.
Think of the DOM as the “mothership” for everything we’ll do to interact with web browsers. All modifications and interactions will be governed by its structure and principles.
Here’s a roadmap for this chapter:
- Understanding the Document Object Model (DOM): We’ll delve into what the DOM is and how it represents web pages.
- Modifying Web Page Content: We’ll learn techniques to add, change, and remove elements and text on a webpage dynamically.
- Responding to User Events: We’ll explore how to use JavaScript to react to events like clicks and mouse movements, making our pages interactive.
- Creating a Pop-up Effect: We’ll synthesize our learning by building a practical pop-up feature on a webpage.
Setting Up Your Development Environment: Live Server
For this chapter, and for much of what we’ll be doing moving forward, it’s crucial to have a web server running to preview your work in a browser. A web server, in this context, allows you to view your HTML, CSS, and JavaScript files as they would appear on a live website, handling requests and providing the necessary environment for JavaScript to interact with the web page correctly.
Web Server: In web development, a web server is software and hardware that uses HTTP (Hypertext Transfer Protocol) and other protocols to respond to client requests made over the World Wide Web. It primarily serves web pages and related content to clients.
If you’ve forgotten how to set up a local development server, let’s quickly revisit the Live Server package in VS Code.
VS Code (Visual Studio Code): A popular source code editor developed by Microsoft for Windows, Linux and macOS. It includes support for debugging, embedded Git control, syntax highlighting, intelligent code completion, snippets, and code refactoring.
Steps to Use Live Server in VS Code:
-
Install the Live Server Package:
- Open VS Code.
- Navigate to the Extensions view (usually by clicking on the Extensions icon in the Activity Bar on the side or pressing
Ctrl+Shift+X
orCmd+Shift+X
). - Search for “Live Server” in the extensions marketplace.
- Find the “Live Server” extension by Ritwick Dey and click “Install”.
-
Open Your HTML File with Live Server:
- Locate the HTML file you wish to preview in your VS Code Explorer.
- Right-click on the HTML file.
- Select “Open with Live Server” from the context menu.
This action will:
- Start a local development server on your computer.
- Open your HTML page in your default web browser, pointing to the local server address.
- Automatically refresh the browser whenever you save changes to your HTML, CSS, or JavaScript files, allowing for immediate feedback and a streamlined development workflow.
Ensure you have Live Server running for the duration of this chapter and for most of the upcoming course content. It’s an indispensable tool for dynamic web development.
Understanding the Document Object Model (DOM)
The Document Object Model (DOM) is at the heart of web page manipulation with JavaScript. But what exactly is it?
Simply put, the DOM is a representation of your HTML document as a tree-like structure of nodes, created by the browser when an HTML document is loaded. Imagine your HTML page with all its tags and content. The browser parses this HTML and transforms it into an object model – the DOM.
This object model is crucial because it provides JavaScript code with a way to access and interact with every element of the HTML document. Our goal is to use JavaScript to:
- Access specific HTML elements.
- Modify their content, styles, and attributes.
- Respond to user actions on these elements.
Think of it this way:
- HTML Document Loads: When a browser loads an HTML document, it reads the HTML code.
- DOM Creation: The browser then creates a Document Object. This object represents the entire HTML document in a structured, object-oriented way.
- JavaScript Interaction: JavaScript code can then access and manipulate this
document
object to interact with the web page.
Exploring the Document Object in the Browser Console
We can observe the Document Object in action using the browser’s console.
Browser Console: A tool built into web browsers that provides a way to log information related to a web page, including JavaScript errors, network requests, and messages explicitly logged by JavaScript code. It also allows developers to interact with the webpage using JavaScript commands.
Steps to Access the Browser Console:
- Open your web page in a browser (preferably using Live Server as set up earlier).
- Right-click anywhere on the webpage.
- Select “Inspect” or “Inspect Element” (the exact wording may vary slightly depending on your browser).
- In the Developer Tools panel that appears, navigate to the “Console” tab.
Once in the console, type document
and press Enter. You will see the document
object logged to the console.
If you expand this object, you might initially be surprised. Instead of seeing methods and properties directly, you’ll see a visual representation of your HTML page structure, mirroring the “Elements” tab in the Developer Tools. This visual representation is the browser’s way of showing you the DOM tree.
However, the document
object does have a vast array of properties and methods that we can use programmatically.
Object (in programming): In object-oriented programming, an object is a self-contained entity that bundles together data (properties) and behavior (methods). In JavaScript, objects are fundamental and used extensively.
Property (of an object): A property is a characteristic or attribute of an object, representing data associated with the object. You can access and modify object properties.
Method (of an object): A method is a function that is associated with an object and can be called to perform actions on that object or its data.
To explore these properties and methods, type document.
(document followed by a dot) in the console and observe the auto-completion suggestions. You’ll see a long list of available properties and methods.
Examples:
document.location
: This property returns an object containing information about the current URL (Uniform Resource Locator) of the document, including thehref
(hypertext reference).document.URL
: This property returns a string representing the URL of the document.document.getElementById()
,document.querySelector()
,document.getElementsByClassName()
: These are methods used to select specific elements within the HTML document, which we’ll explore in detail later.
These properties and methods allow us to programmatically interact with the HTML page through the DOM.
The DOM as a Hierarchical Tree of Nodes
The DOM describes the HTML page as a hierarchical tree of nodes. Imagine your HTML structure:
<!DOCTYPE html>
<html>
<head>
<title>My Webpage</title>
</head>
<body>
<h1>Welcome</h1>
<div class="container">
<p>This is some text.</p>
</div>
</body>
</html>
The DOM represents this as a tree where:
- The
<html>
tag is the root node – the starting point of the tree. - Inside
<html>
are the<head>
and<body>
tags, which are children nodes of the root node. - Within
<head>
is the<title>
tag, and within<body>
are<h1>
and<div>
, and so on. - The text content within tags (like “Welcome” inside
<h1>
or “This is some text.” inside<p>
) are also considered nodes, specifically text nodes. - The HTML tags themselves are element nodes.
Node (in DOM): A node is a basic unit in the DOM tree. Each HTML element, attribute, or piece of text within the HTML document is represented as a node in the DOM tree.
Root Node (in DOM): The topmost node in the DOM tree, representing the entire document. In HTML documents, the root node is typically the
<html>
element.
Element Node (in DOM): A node in the DOM tree that represents an HTML element, such as
<div>
,<p>
,<h1>
, etc.
Text Node (in DOM): A node in the DOM tree that represents the text content within an HTML element.
This hierarchical structure is crucial. To interact with a specific element on the page (e.g., the <h1>
heading), we use the DOM to “reach into” this tree, navigate through the nodes, and get a reference to the desired node.
Once we have a reference to an element node, we can use various methods provided by the DOM to:
- Change its content (using properties like
innerText
orinnerHTML
). - Modify its style (using the
style
property or manipulating classes). - Remove it from the page.
- Add new elements as its children.
- And much more.
Keep this mental image of the DOM as a tree in mind as we move forward. It will be invaluable as we learn to navigate and manipulate web pages with JavaScript.
Querying the DOM: Selecting Elements
Now that we understand what the DOM is, let’s learn how to query it – that is, how to select specific HTML elements so we can interact with them.
When working with the DOM to modify web page content, the process generally involves two key steps:
- Querying (Selecting) Elements: First, we need to identify which element(s) on the page we want to work with. This is done by “querying” the DOM to get a reference to those elements.
Querying the DOM: The process of selecting or retrieving specific HTML elements from the Document Object Model (DOM) using JavaScript methods. This allows you to access and manipulate those elements.
- Manipulation: Once we have a reference to the element(s), we can then perform actions on them, such as changing their content, style, or attributes.
In this section, we’ll focus on the first step: querying the DOM to get references to elements.
Using querySelector()
and querySelectorAll()
The most versatile and recommended methods for querying the DOM are querySelector()
and querySelectorAll()
, both available on the document
object. These methods use CSS selectors to target elements.
CSS Selectors: Patterns used to select the element(s) you want to style or manipulate in CSS (Cascading Style Sheets). JavaScript’s
querySelector
andquerySelectorAll
methods leverage these same selector patterns.
If you need a refresher on CSS selectors, consider reviewing resources on CSS selectors. However, we’ll cover the basics here.
querySelector()
: Selecting a Single Element
The querySelector()
method selects the first element that matches a given CSS selector.
Syntax:
const elementReference = document.querySelector('cssSelector');
'cssSelector'
is a string containing a valid CSS selector (e.g., tag name, class, ID, etc.).elementReference
is a variable where we store the reference to the selected HTML element.
Examples (based on the provided transcript’s index.html
structure):
HTML Snippet (from transcript example):
<p>Hello, world!</p>
<p class="error">This is an error message.</p>
<p>Another paragraph.</p>
<div class="error">This is another error (div).</div>
JavaScript Examples:
-
Select the first
<p>
tag:const firstParagraph = document.querySelector('p'); console.log(firstParagraph); // Output: <p>Hello, world!</p>
This will select the very first
<p>
tag encountered in the HTML document. -
Select the first
<p>
tag with the class “error”:const errorParagraph = document.querySelector('.error'); // Note the '.' for class selector console.log(errorParagraph); // Output: <p class="error">This is an error message.</p>
The
.
prefix in.error
indicates a class selector in CSS syntax. -
Select a
<div>
tag with the class “error”:const errorDiv = document.querySelector('div.error'); // Combine tag and class selector console.log(errorDiv); // Output: <div class="error">This is another error (div).</div>
This selector targets only
<div>
elements that also have the class “error”. -
Select an element using its ID (if it had one, e.g.,
<h1 id="main-heading">
):const heading = document.querySelector('#main-heading'); // Note the '#' for ID selector console.log(heading); // Output: <h1 id="main-heading">Welcome</h1> (if it existed)
The
#
prefix in#main-heading
indicates an ID selector.
Tip: Copying CSS Selectors from Browser DevTools:
If you’re unsure of the correct CSS selector for a specific element, you can use the browser’s Developer Tools to help:
- Right-click on the element in the “Elements” tab of the Developer Tools.
- Select “Copy” -> “Copy selector”.
- Paste the copied selector into your
querySelector()
method.
This will often provide a unique and precise CSS selector for the element you selected.
querySelectorAll()
: Selecting Multiple Elements
The querySelectorAll()
method selects all elements that match a given CSS selector and returns them as a NodeList.
Syntax:
const elementCollection = document.querySelectorAll('cssSelector');
'cssSelector'
is a string containing a valid CSS selector.elementCollection
is a variable holding a NodeList of all matching HTML elements.
NodeList: A collection of nodes extracted from a document. It’s similar to an array, but not a true JavaScript array. NodeLists are often returned by DOM query methods that can select multiple elements.
Example:
-
Select all
<p>
tags:const allParagraphs = document.querySelectorAll('p'); console.log(allParagraphs); // Output: NodeList [p, p.error, p]
This will return a NodeList containing references to all three
<p>
elements in our example HTML.
Working with NodeLists:
NodeLists are array-like but not true arrays. Key things to know:
-
Accessing Elements: You can access individual elements in a NodeList using bracket notation (like arrays), starting from index 0.
console.log(allParagraphs[0]); // Output: <p>Hello, world!</p> (the first <p> tag) console.log(allParagraphs[2]); // Output: <p>Another paragraph.</p> (the third <p> tag)
-
Iteration with
forEach()
: You can iterate over a NodeList using theforEach()
method, similar to arrays.allParagraphs.forEach(paragraph => { console.log(paragraph.textContent); // Output: the text content of each <p> tag });
forEach()
(method): A method available on array-like objects (like NodeLists and Arrays) that executes a provided function once for each element in the NodeList or array. -
Not all Array Methods Available: NodeLists do not have all the methods that standard JavaScript arrays have (e.g.,
map()
,filter()
,reduce()
). If you need to use full array methods, you might need to convert the NodeList to an array first.
Example: Selecting all elements with the class “error”:
const errorElements = document.querySelectorAll('.error');
console.log(errorElements); // Output: NodeList [p.error, div.error] (both elements with class 'error')
errorElements.forEach(errorElement => {
console.log(errorElement.tagName); // Output: "P", then "DIV" (tag names of error elements)
});
querySelector()
and querySelectorAll()
are powerful tools for precisely targeting elements within the DOM using the familiar syntax of CSS selectors.
Alternative DOM Query Methods
While querySelector()
and querySelectorAll()
are generally preferred for their flexibility, there are older, more specific DOM query methods that can also be useful in certain situations.
getElementById()
: Selecting by ID
The getElementById()
method selects a single element based on its id
attribute. IDs should be unique within an HTML document.
Syntax:
const elementReference = document.getElementById('elementId');
'elementId'
is a string representing theid
attribute value of the element you want to select (e.g., “page-title”).- Important: You only need to provide the ID value itself, without the
#
prefix used in CSS selectors. The method name itself implies that you are selecting by ID.
Example (assuming an HTML element like <h1 id="page-title">
):
const titleElement = document.getElementById('page-title');
console.log(titleElement); // Output: <h1 id="page-title">...</h1>
getElementsByClassName()
: Selecting by Class Name
The getElementsByClassName()
method selects all elements that have a specific class name.
Syntax:
const elementCollection = document.getElementsByClassName('className');
'className'
is a string representing the class name (e.g., “error”).- Important: You only need to provide the class name, without the
.
prefix used in CSS selectors. The method name itself implies that you are selecting by class name. - This method returns an HTMLCollection, not a NodeList.
HTMLCollection: Similar to a NodeList, an HTMLCollection is a collection of HTML elements. It’s also array-like, but with some key differences from NodeLists and true arrays. One key difference is that HTMLCollections are live, meaning they automatically update if the DOM changes.
Example (selecting all elements with the class “error”):
const errorElementsCollection = document.getElementsByClassName('error');
console.log(errorElementsCollection); // Output: HTMLCollection [p.error, div.error]
Key Difference: HTMLCollection vs. NodeList:
-
getElementsByClassName()
andgetElementsByTagName()
return HTMLCollections. -
querySelectorAll()
returns NodeLists. -
HTMLCollections are “live”: If the DOM changes, the HTMLCollection is automatically updated to reflect those changes. NodeLists are generally static (snapshots of the DOM at the time of selection).
-
forEach()
not directly available on HTMLCollections: You cannot directly useforEach()
on an HTMLCollection. You would need to convert it to an array first if you want to useforEach()
.// Example of converting HTMLCollection to array to use forEach (if needed): const errorElementsArray = Array.from(errorElementsCollection); errorElementsArray.forEach(element => { console.log(element.tagName); });
getElementsByTagName()
: Selecting by Tag Name
The getElementsByTagName()
method selects all elements with a specific tag name (e.g., all <p>
tags, all <div>
tags).
Syntax:
const elementCollection = document.getElementsByTagName('tagName');
'tagName'
is a string representing the HTML tag name (e.g., “p”, “div”, “h1”).- This method also returns an HTMLCollection.
Example (selecting all <p>
tags):
const paragraphCollection = document.getElementsByTagName('p');
console.log(paragraphCollection); // Output: HTMLCollection [p, p.error, p]
Choosing the Right Query Method
While all these methods achieve the goal of selecting DOM elements, querySelector()
and querySelectorAll()
are generally favored for modern JavaScript development because:
- Flexibility: They use CSS selectors, which are a powerful and standardized way to target elements based on various criteria (tag name, class, ID, attributes, relationships, etc.).
- Consistency: They are more consistent in their behavior and return NodeLists, which are generally easier to work with than HTMLCollections in many cases.
- Familiarity (for web developers): Web developers are typically already familiar with CSS selectors from styling web pages.
However, getElementById()
, getElementsByClassName()
, and getElementsByTagName()
are still valid and can be useful in specific scenarios, particularly if you need the “live” updating behavior of HTMLCollections or if you are working with older codebases.
For most situations, especially when starting new projects, querySelector()
and querySelectorAll()
are the recommended and most versatile choices for querying the DOM.
Modifying Element Content: Text and HTML
Once we have successfully queried the DOM and obtained references to HTML elements, the next step is to manipulate them. One of the most common manipulations is changing the content inside an element. We can modify both the plain text content and the HTML content.
Changing Text Content with innerText
The innerText
property of an HTML element allows you to get or set the plain text content of that element. It only considers the rendered text that is visible on the page, ignoring HTML tags within the element.
Getting Text Content:
const paragraphElement = document.querySelector('p'); // Get a reference to a <p> tag
const textInside = paragraphElement.innerText;
console.log(textInside); // Output: the text content of the paragraph
Setting Text Content:
const paragraphElement = document.querySelector('p');
paragraphElement.innerText = 'This is the new text content.'; // Set new text
This will replace the existing text content of the paragraph element with “This is the new text content.”.
Example: Changing the text of multiple paragraphs:
const allParagraphs = document.querySelectorAll('p');
allParagraphs.forEach(paragraph => {
paragraph.innerText += ' - added text'; // Append text to each paragraph
});
This code will loop through all <p>
tags on the page and append ” - added text” to their existing text content.
Changing HTML Content with innerHTML
The innerHTML
property is more powerful than innerText
. It allows you to get or set the HTML content within an element. This means you can not only change text but also insert new HTML tags and structures dynamically.
Getting HTML Content:
const divElement = document.querySelector('.content'); // Get a <div> with class 'content'
const htmlInside = divElement.innerHTML;
console.log(htmlInside); // Output: the HTML content inside the div (including tags)
Setting HTML Content:
const divElement = document.querySelector('.content');
divElement.innerHTML = '<h2>This is a new heading inside the div</h2><p>And some new paragraph text.</p>';
This will completely replace the existing HTML content of the div
element with a new <h2>
heading and a <p>
paragraph.
Example: Appending HTML content:
const contentDiv = document.querySelector('.content');
contentDiv.innerHTML += '<p>This paragraph was added dynamically.</p>'; // Append HTML
Using +=
with innerHTML
allows you to append HTML content without overwriting the existing content.
Example: Generating HTML from data:
const people = ['Muriel', 'Luigi', 'Yoshi'];
const contentDiv = document.querySelector('.content');
let htmlOutput = ''; // Start with an empty string
people.forEach(person => {
htmlOutput += `<p>${person}</p>`; // Build up HTML string for each person
});
contentDiv.innerHTML = htmlOutput; // Set the entire HTML content of the div
This example demonstrates how to dynamically generate HTML content based on data (in this case, an array of names) and then inject it into the webpage using innerHTML
. This is a fundamental technique for creating dynamic web pages that display data retrieved from databases or APIs.
Important Security Note about innerHTML
:
While innerHTML
is powerful, it’s crucial to be cautious when using it to insert content that comes from untrusted sources (e.g., user input). If you insert untrusted HTML using innerHTML
, it could potentially introduce Cross-Site Scripting (XSS) vulnerabilities, where malicious scripts could be injected into your webpage and executed.
For handling user-generated content or data from external sources, consider using methods that sanitize or escape HTML to prevent XSS attacks, or explore safer alternatives for DOM manipulation when possible. For simple, controlled content manipulation within your own code, innerHTML
is often convenient and effective.
Working with HTML Attributes
In addition to content, we can also manipulate HTML attributes of elements using JavaScript. Attributes provide extra information about HTML elements (e.g., href
for links, src
for images, class
for styling).
Getting Attribute Values with getAttribute()
The getAttribute()
method allows you to retrieve the value of a specific attribute of an HTML element.
Syntax:
const attributeValue = elementReference.getAttribute('attributeName');
'attributeName'
is a string representing the name of the attribute you want to get (e.g., ‘href’, ‘class’, ‘id’).
Examples (based on example HTML with <a href="https://www.google.com">
and <p class="error">
):
-
Get the
href
attribute value of a link:const linkElement = document.querySelector('a'); const linkHref = linkElement.getAttribute('href'); console.log(linkHref); // Output: "https://www.google.com"
-
Get the
class
attribute value of a paragraph:const errorParagraph = document.querySelector('.error'); const paragraphClass = errorParagraph.getAttribute('class'); console.log(paragraphClass); // Output: "error"
Setting Attribute Values with setAttribute()
The setAttribute()
method allows you to set or modify the value of an HTML attribute.
Syntax:
elementReference.setAttribute('attributeName', 'newValue');
'attributeName'
is the name of the attribute to set.'newValue'
is the new value you want to assign to the attribute (as a string).
Examples:
-
Change the
href
attribute of a link:const linkElement = document.querySelector('a'); linkElement.setAttribute('href', 'https://www.thenetninja.co.uk'); linkElement.innerText = 'The Net Ninja Website'; // Update link text to reflect change
This will change the link’s destination and update its displayed text.
-
Change the
class
attribute of a paragraph:const messageParagraph = document.querySelector('.error'); // Assuming it initially has class 'error' messageParagraph.setAttribute('class', 'success'); // Change class to 'success'
This will change the CSS class applied to the paragraph, potentially altering its styling if you have CSS rules defined for the “success” class.
-
Set a
style
attribute to apply inline styles:const paragraphElement = document.querySelector('p'); paragraphElement.setAttribute('style', 'color: green;'); // Add inline style to make text green
While you can use
setAttribute('style', ...)
to apply inline styles, it’s often more flexible and maintainable to manipulate styles using thestyle
property directly (which we’ll discuss next) or by adding/removing CSS classes. -
Adding a new attribute that doesn’t initially exist:
const paragraphElement = document.querySelector('p'); paragraphElement.setAttribute('data-custom-info', 'This is custom data'); // Add a custom data attribute
You can even add custom attributes (often prefixed with
data-
) to elements usingsetAttribute()
. These can be useful for storing application-specific data directly in the HTML.
getAttribute()
and setAttribute()
are essential for dynamically modifying the properties and behaviors of HTML elements by working with their attributes.
Styling Elements with JavaScript: Inline Styles and CSS Classes
We’ve already seen how to set inline styles using setAttribute('style', ...)
. However, JavaScript provides a more direct and often more convenient way to manipulate element styles through the style
property. Furthermore, we’ll explore how to effectively manage styles by adding and removing CSS classes using JavaScript.
Manipulating Inline Styles with the style
Property
Every HTML element in the DOM has a style
property. This property is itself an object that contains properties corresponding to CSS style rules.
Accessing Inline Styles:
const headingElement = document.querySelector('h1');
const headingStyle = headingElement.style;
console.log(headingStyle); // Output: CSSStyleDeclaration object (containing style properties)
The headingStyle
object will contain properties for various CSS styles. Initially, most of these will likely be empty strings unless inline styles are already set on the element in the HTML.
Getting a Specific Style Property:
const headingElement = document.querySelector('h1');
const headingColor = headingElement.style.color;
console.log(headingColor); // Output: The current color style value (e.g., "orange" if set inline)
Setting a Style Property:
const headingElement = document.querySelector('h1');
headingElement.style.margin = '50px'; // Set margin style
headingElement.style.color = 'crimson'; // Set color style
This will directly apply inline styles to the heading element.
Important: Camel Case for CSS Properties in JavaScript:
When setting CSS style properties in JavaScript using the style
property, you need to use camel case for CSS property names that are typically hyphenated in CSS (e.g., font-size
becomes fontSize
, background-color
becomes backgroundColor
).
Examples:
font-size
in CSS becomesfontSize
in JavaScript (element.style.fontSize = '60px';
)background-color
becomesbackgroundColor
(element.style.backgroundColor = 'lightblue';
)border-left-color
becomesborderLeftColor
(element.style.borderLeftColor = 'red';
)
Removing an Inline Style:
To remove an inline style that you’ve set with JavaScript, you can set its value to an empty string:
const headingElement = document.querySelector('h1');
headingElement.style.margin = ''; // Remove the margin style
Advantages of using the style
property:
- Direct Manipulation: It provides a straightforward way to directly modify inline styles.
- Adding Styles without Overwriting: Unlike
setAttribute('style', ...)
, using thestyle
property to set individual styles generally adds to existing inline styles without completely overwriting them (unless you are setting the same style property again).
Limitations of Inline Styles:
- Specificity: Inline styles have the highest CSS specificity, which can make them harder to override with external stylesheets or CSS classes later on.
- Maintainability: Overuse of inline styles can make your HTML less clean and harder to maintain compared to using CSS classes defined in stylesheets.
Managing Styles with CSS Classes: classList
A more robust and maintainable approach to styling elements dynamically with JavaScript is to manipulate CSS classes. This involves:
-
Defining CSS Classes in Stylesheets: You define your CSS styles in external stylesheets or within
<style>
tags in your HTML. These styles are associated with CSS classes (e.g.,.error
,.success
,.highlight
). -
Adding, Removing, or Toggling Classes with JavaScript: You use JavaScript to add, remove, or toggle these CSS classes on HTML elements. The browser will then automatically apply or remove the corresponding styles defined in your stylesheets.
The classList
property of an HTML element provides methods for working with its CSS classes.
Accessing the classList
:
const paragraphElement = document.querySelector('.error');
const classes = paragraphElement.classList;
console.log(classes); // Output: DOMTokenList ['error', value: 'error'] (a list of classes)
The classList
is a DOMTokenList, which is an array-like object representing the classes of an element.
Methods of classList
:
-
add(className)
: Adds a CSS class to the element’sclass
attribute.const paragraphElement = document.querySelector('p'); paragraphElement.classList.add('highlight'); // Add the class 'highlight'
-
remove(className)
: Removes a CSS class from the element’sclass
attribute.const paragraphElement = document.querySelector('.error'); paragraphElement.classList.remove('error'); // Remove the class 'error'
-
toggle(className)
: Toggles a CSS class. If the class is present, it removes it. If the class is absent, it adds it.const buttonElement = document.querySelector('button'); // Example button buttonElement.addEventListener('click', () => { buttonElement.classList.toggle('active'); // Toggle 'active' class on each click });
-
contains(className)
: Checks if the element has a specific class. Returnstrue
if the class is present,false
otherwise.const paragraphElement = document.querySelector('.highlight'); if (paragraphElement.classList.contains('highlight')) { console.log('Paragraph has the class "highlight"'); }
Example: Applying error and success classes based on text content:
const allParagraphs = document.querySelectorAll('p');
allParagraphs.forEach(paragraph => {
const textContent = paragraph.textContent.toLowerCase(); // To make case-insensitive
if (textContent.includes('error')) {
paragraph.classList.add('error');
} else if (textContent.includes('success')) {
paragraph.classList.add('success');
}
// You could add an 'else' block to remove classes if needed, or leave elements without 'error' or 'success' classes as they are.
});
This code iterates through paragraphs and adds the “error” or “success” class based on whether the paragraph’s text content includes “error” or “success” (case-insensitively). You would need to have CSS rules defined for the .error
and .success
classes in your stylesheet for the styling to be applied.
Advantages of using classList
and CSS Classes:
- Maintainability: Styles are defined in CSS stylesheets, keeping your JavaScript focused on logic and DOM manipulation, and your CSS focused on styling.
- Reusability: CSS classes can be reused across multiple elements and pages, promoting consistency and reducing code duplication.
- Specificity Management: CSS classes allow you to control CSS specificity more effectively compared to inline styles.
- Separation of Concerns: Separates styling (CSS) from behavior (JavaScript), leading to cleaner and more organized codebases.
In most web development scenarios, manipulating CSS classes using classList
is the preferred and more scalable approach to dynamically styling elements with JavaScript, as it promotes better organization, maintainability, and separation of concerns.
Conclusion and Further Learning
Congratulations! You’ve completed this introductory chapter on dynamic web pages with JavaScript and the Document Object Model (DOM). We’ve covered a wide range of essential concepts and techniques, including:
- Understanding the Document Object Model (DOM) and its tree-like structure.
- Setting up a local development environment with Live Server.
- Querying the DOM using
querySelector()
,querySelectorAll()
, and alternative methods likegetElementById()
,getElementsByClassName()
, andgetElementsByTagName()
. - Modifying element content using
innerText
andinnerHTML
. - Working with HTML attributes using
getAttribute()
andsetAttribute()
. - Styling elements dynamically using the
style
property for inline styles and, more importantly, manipulating CSS classes withclassList
methods (add()
,remove()
,toggle()
).
These foundational skills are crucial for building interactive and dynamic web applications. As you continue your JavaScript journey, you’ll build upon these concepts to create increasingly complex and engaging web experiences.
To further enhance your JavaScript skills and delve deeper into advanced topics, consider exploring resources that cover:
- Event Handling in Detail: We’ve touched on events briefly, but a deeper understanding of event listeners, event propagation, and different event types (mouse, keyboard, form events, etc.) is essential for interactive web development.
- Asynchronous JavaScript and AJAX: Learn how to make asynchronous requests to servers (using AJAX or
fetch API
) to retrieve data dynamically and update web pages without full page reloads. - Working with APIs: Explore various web APIs provided by browsers, such as the Geolocation API, Canvas API, Web Storage API, and more, to add rich functionality to your web applications.
- Object-Oriented Programming in JavaScript: A deeper understanding of OOP principles in JavaScript will help you structure larger and more complex applications effectively.
- JavaScript Frameworks and Libraries: Consider learning popular JavaScript frameworks like React, Angular, or Vue.js, which provide powerful tools and abstractions for building complex user interfaces and single-page applications.
The possibilities with JavaScript and the DOM are vast. Keep practicing, experimenting, and building projects to solidify your understanding and expand your skillset. Happy coding!