JavaScript Course

Course Overview

JavaScript is a versatile programming language that is essential for web development. It allows you to create dynamic and interactive web pages.

What is JavaScript?

JavaScript is a programming language commonly used in web development. It was originally developed by Netscape as a means to add dynamic and interactive elements to websites.

Setting Up Your Environment

To start writing JavaScript, all you need is a text editor and a web browser. You can write JavaScript directly in your HTML file using the <script> tag.

Writing Your First JavaScript Program

Create a new HTML file and add the following code to write "Hello, World!" to the console:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World</title>
</head>
<body>
    <script>
        console.log('Hello, World!');
    </script>
</body>
</html>

Declaring Variables

Variables in JavaScript can be declared using var, let, or const. The let and const keywords were introduced in ES6 and provide block-scoping:

// Using var
var name = 'John';
console.log(name);

// Using let
let age = 25;
console.log(age);

// Using const
const pi = 3.14;
console.log(pi);

Data Types

JavaScript supports various data types including:

  • Number: for numeric values
  • String: for text
  • Boolean: for true/false values
  • Object: for collections of data
  • Array: for ordered lists of data
  • Undefined: for variables that have not been assigned a value
  • Null: for variables that have been explicitly set to no value
// Number
let number = 5;

// String
let text = "Hello";

// Boolean
let isValid = true;

// Object
let person = {
    name: "John",
    age: 30
};

// Array
let numbers = [1, 2, 3, 4, 5];

// Undefined
let x;

// Null
let y = null;

Arithmetic Operators

JavaScript supports arithmetic operators like addition, subtraction, multiplication, division, and modulus:

let a = 10;
let b = 5;

console.log(a + b);  // 15
console.log(a - b);  // 5
console.log(a * b);  // 50
console.log(a / b);  // 2
console.log(a % b);  // 0

Comparison Operators

Comparison operators are used to compare values:

let a = 10;
let b = 5;

console.log(a == b);  // false
console.log(a != b);  // true
console.log(a > b);   // true
console.log(a < b);   // false
console.log(a >= b);  // true
console.log(a <= b);  // false

Logical Operators

Logical operators are used to combine conditional statements:

let a = true;
let b = false;

console.log(a && b);  // false
console.log(a || b);  // true
console.log(!a);      // false

Conditional Statements

Use if, else if, and else to execute code based on conditions:

let age = 20;

if (age < 18) {
    console.log("You are a minor.");
} else if (age < 65) {
    console.log("You are an adult.");
} else {
    console.log("You are a senior.");
}

Switch Statement

The switch statement is used to perform different actions based on different conditions:

let fruit = "apple";

switch(fruit) {
case "banana":
console.log("This is a banana.");
break;
case "apple":
console.log("This is an apple.");
break;
case "orange":
console.log("This is an orange.");
break;
default:
console.log("Unknown fruit.");
}

Loops

JavaScript supports various types of loops for repeating blocks of code:

  • for loop
  • while loop
  • do...while loop
  • for...in loop
  • for...of loop
// for loop
for (let i = 0; i < 5; i++) {
console.log(i);
}

// while loop
let i = 0;
while (i < 5) {
console.log(i);
i++;
}

// do...while loop
let j = 0;
do {
console.log(j);
j++;
} while (j < 5);

// for...in loop
let person = {name: "John", age: 30};
for (let key in person) {
console.log(key + ": " + person[key]);
}

// for...of loop
let numbers = [1, 2, 3, 4, 5];
for (let number of numbers) {
console.log(number);
}

Defining Functions

Functions are defined using the function keyword. They can take parameters and return values:

function greet(name) {
return "Hello, " + name + "!";
}

console.log(greet("John"));  // Hello, John!

Function Expressions

Functions can also be defined as expressions:

const greet = function(name) {
return "Hello, " + name + "!";
};

console.log(greet("Jane"));  // Hello, Jane!

Arrow Functions

Arrow functions provide a shorter syntax for writing functions:

const greet = (name) => "Hello, " + name + "!";

console.log(greet("Jack"));  // Hello, Jack!

Creating Objects

Objects are collections of key-value pairs. They can be created using object literals:

let person = {
name: "John",
age: 30,
greet: function() {
return "Hello, " + this.name + "!";
}
};

console.log(person.name);  // John
console.log(person.greet());  // Hello, John!

Constructor Functions

Constructor functions are used to create multiple objects with similar properties:

function Person(name, age) {
this.name = name;
this.age = age;
this.greet = function() {
return "Hello, " + this.name + "!";
};
}

let john = new Person("John", 30);
let jane = new Person("Jane", 25);

console.log(john.greet());  // Hello, John!
console.log(jane.greet());  // Hello, Jane!

Prototypes

Prototypes allow you to add properties and methods to objects:

function Person(name, age) {
this.name = name;
this.age = age;
}

Person.prototype.greet = function() {
return "Hello, " + this.name + "!";
};

let john = new Person("John", 30);
console.log(john.greet());  // Hello, John!

Selecting Elements

Use methods like getElementById, getElementsByClassName, and querySelector to select HTML elements:

// Select by ID
let header = document.getElementById("header");

// Select by class name
let items = document.getElementsByClassName("item");

// Select by CSS selector
let firstItem = document.querySelector(".item");

Changing Element Content

Change the content of HTML elements using properties like innerText and innerHTML:

// Change innerText
header.innerText = "New Header Text";

// Change innerHTML
firstItem.innerHTML = "New Item Content";

Adding and Removing Elements

Add and remove elements from the DOM using methods like appendChild and removeChild:

// Create a new element
let newItem = document.createElement("div");
newItem.className = "item";
newItem.innerText = "New Item";

// Add the new element to the DOM
document.body.appendChild(newItem);

// Remove an element from the DOM
document.body.removeChild(newItem);

Adding Event Listeners

Add event listeners to HTML elements to handle events like clicks, mouse movements, and key presses:

// Select an element
let button = document.querySelector("button");

// Add a click event listener
button.addEventListener("click", function() {
alert("Button clicked!");
});

Common Events

Some common events include:

  • click: when an element is clicked
  • mouseover: when the mouse is over an element
  • mouseout: when the mouse leaves an element
  • keydown: when a key is pressed
  • keyup: when a key is released
// Mouseover event
button.addEventListener("mouseover", function() {
button.style.backgroundColor = "yellow";
});

// Mouseout event
button.addEventListener("mouseout", function() {
button.style.backgroundColor = "";
});

// Keydown event
document.addEventListener("keydown", function(event) {
console.log("Key pressed: " + event.key);
});

// Keyup event
document.addEventListener("keyup", function(event) {
console.log("Key released: " + event.key);
});

Let and Const

The let and const keywords provide block-scoping, which helps prevent bugs caused by variable hoisting:

let x = 10;
if (true) {
let x = 20;  // This x is different from the outer x
console.log(x);  // 20
}
console.log(x);  // 10

const y = 30;
console.log(y);  // 30

// y = 40;  // Error: Assignment to constant variable

Arrow Functions

Arrow functions provide a concise way to write functions:

const add = (a, b) => a + b;
console.log(add(2, 3));  // 5

Template Literals

Template literals allow you to embed expressions inside string literals, using backticks (`) instead of single or double quotes:

let name = "John";
let message = `Hello, ${name}!`;
console.log(message);  // Hello, John!

Destructuring

Destructuring allows you to extract values from arrays or properties from objects into distinct variables:

// Array destructuring
let [a, b] = [1, 2];
console.log(a);  // 1
console.log(b);  // 2

// Object destructuring
let person = {name: "John", age: 30};
let {name, age} = person;
console.log(name);  // John
console.log(age);  // 30

Classes

Classes provide a more convenient and clearer syntax to create objects and deal with inheritance:

class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}

greet() {
return `Hello, my name is ${this.name} and I am ${this.age} years old.`;
}
}

let john = new Person("John", 30);
console.log(john.greet());  // Hello, my name is John and I am 30 years old.

Callbacks

Callbacks are functions passed as arguments to other functions to be executed after an operation is completed:

function fetchData(callback) {
setTimeout(() => {
callback("Data received");
}, 2000);
}

fetchData(data => {
console.log(data);  // Data received
});

Promises

Promises provide a more elegant way to handle asynchronous operations:

let promise = new Promise((resolve, reject) => {
let success = true;
if (success) {
resolve("Operation successful");
} else {
reject("Operation failed");
}
});

promise.then(result => {
console.log(result);  // Operation successful
}).catch(error => {
console.log(error);
});

Async/Await

The async and await keywords provide a way to write asynchronous code that looks synchronous:

async function fetchData() {
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("Data received"), 2000);
});

let result = await promise;
console.log(result);  // Data received
}

fetchData();

Importing and Exporting Modules

Modules in JavaScript allow you to break your code into separate files. Use the export and import keywords to work with modules:

// math.js
export function add(a, b) {
return a + b;
}

export function subtract(a, b) {
return a - b;
}

// main.js
import { add, subtract } from './math.js';

console.log(add(2, 3));  // 5
console.log(subtract(5, 2));  // 3

Try...Catch

Use try...catch blocks to handle errors in JavaScript:

try {
let result = riskyOperation();
console.log(result);
} catch (error) {
console.error("An error occurred:", error);
}

Throwing Errors

You can throw your own errors using the throw statement:

function riskyOperation() {
if (Math.random() > 0.5) {
throw new Error("Something went wrong!");
}
return "Success!";
}

try {
let result = riskyOperation();
console.log(result);
} catch (error) {
console.error("An error occurred:", error);
}

Finally Block

The finally block contains code that will be executed regardless of whether an error occurred:

try {
let result = riskyOperation();
console.log(result);
} catch (error) {
console.error("An error occurred:", error);
} finally {
console.log("This will always run");
}

Introduction to AJAX

AJAX (Asynchronous JavaScript and XML) allows you to send and receive data asynchronously without reloading the web page. You can use the XMLHttpRequest object to make AJAX requests:

let xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.example.com/data", true);
xhr.onload = function() {
if (xhr.status === 200) {
console.log(xhr.responseText);
} else {
console.error("Request failed");
}
};
xhr.send();

Using the Fetch API

The Fetch API provides a modern interface for making HTTP requests:

fetch("https://api.example.com/data")
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Request failed", error));

Making POST Requests

Use the Fetch API to make POST requests:

fetch("https://api.example.com/data", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ name: "John", age: 30 })
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Request failed", error));

Introduction to JSON

JSON (JavaScript Object Notation) is a lightweight data-interchange format that is easy for humans to read and write, and easy for machines to parse and generate:

let jsonString = '{"name": "John", "age": 30}';
let jsonObject = JSON.parse(jsonString);
console.log(jsonObject.name);  // John

let newJsonString = JSON.stringify(jsonObject);
console.log(newJsonString);  // {"name":"John","age":30}

Parsing JSON

Use JSON.parse() to convert a JSON string into a JavaScript object:

let jsonString = '{"name": "John", "age": 30}';
let jsonObject = JSON.parse(jsonString);
console.log(jsonObject.name);  // John

Stringifying JSON

Use JSON.stringify() to convert a JavaScript object into a JSON string:

let jsonObject = { name: "John", age: 30 };
let jsonString = JSON.stringify(jsonObject);
console.log(jsonString);  // {"name":"John","age":30}

Using Local Storage

Local Storage allows you to store data in the browser that persists even after the browser is closed. Use the localStorage object to interact with local storage:

// Set item in local storage
localStorage.setItem("name", "John");

// Get item from local storage
let name = localStorage.getItem("name");
console.log(name);  // John

// Remove item from local storage
localStorage.removeItem("name");

// Clear all items from local storage
localStorage.clear();

Using Session Storage

Session Storage allows you to store data in the browser that persists until the browser or tab is closed. Use the sessionStorage object to interact with session storage:

// Set item in session storage
sessionStorage.setItem("name", "John");

// Get item from session storage
let name = sessionStorage.getItem("name");
console.log(name);  // John

// Remove item from session storage
sessionStorage.removeItem("name");

// Clear all items from session storage
sessionStorage.clear();

Introduction to Canvas

The Canvas API provides a means for drawing graphics via JavaScript and the HTML <canvas> element:

<canvas id="myCanvas" width="200" height="200" style="border:1px solid #000000;"></canvas>

<script>
let canvas = document.getElementById("myCanvas");
let ctx = canvas.getContext("2d");

// Draw a rectangle
ctx.fillStyle = "#FF0000";
ctx.fillRect(20, 20, 150, 100);
</script>

Drawing Shapes

Use the Canvas API to draw shapes like rectangles, circles, and lines:

<canvas id="myCanvas" width="400" height="400" style="border:1px solid #000000;"></canvas>

<script>
let canvas = document.getElementById("myCanvas");
let ctx = canvas.getContext("2d");

// Draw a rectangle
ctx.fillStyle = "#FF0000";
ctx.fillRect(20, 20, 150, 100);

// Draw a circle
ctx.beginPath();
ctx.arc(200, 200, 40, 0, 2 * Math.PI);
ctx.stroke();

// Draw a line
ctx.moveTo(300, 300);
ctx.lineTo(400, 400);
ctx.stroke();
</script>

Animating on Canvas

Create animations using the Canvas API:

<canvas id="myCanvas" width="400" height="400" style="border:1px solid #000000;"></canvas>

<script>
let canvas = document.getElementById("myCanvas");
let ctx = canvas.getContext("2d");

let x = 0;
let y = 0;

function draw() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = "#FF0000";
    ctx.fillRect(x, y, 50, 50);
    x += 1;
    y += 1;
    requestAnimationFrame(draw);
}

draw();
</script>

Introduction to WebSockets

WebSockets provide a way to open a persistent connection between the client and server and allow for real-time communication:

// Create a new WebSocket connection
let socket = new WebSocket("ws://example.com/socket");

// Event listener for when the connection is opened
socket.onopen = function(event) {
    console.log("WebSocket is open now.");
};

// Event listener for when a message is received
socket.onmessage = function(event) {
    console.log("Received message: " + event.data);
};

// Event listener for when the connection is closed
socket.onclose = function(event) {
    console.log("WebSocket is closed now.");
};

// Event listener for when an error occurs
socket.onerror = function(error) {
    console.log("WebSocket error: " + error.message);
};

// Send a message to the server
socket.send("Hello, server!");

Introduction to Service Workers

Service Workers are scripts that run in the background, separate from the web page, and provide features like offline caching and push notifications:

// Register a service worker
if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js')
    .then(function(registration) {
        console.log('Service Worker registered with scope:', registration.scope);
    }).catch(function(error) {
        console.log('Service Worker registration failed:', error);
    });
}

Service Worker Lifecycle

The Service Worker lifecycle consists of installation, activation, and fetching:

// service-worker.js

// Install event
self.addEventListener('install', function(event) {
    console.log('Service Worker installing.');
});

// Activate event
self.addEventListener('activate', function(event) {
    console.log('Service Worker activating.');
});

// Fetch event
self.addEventListener('fetch', function(event) {
    console.log('Fetching:', event.request.url);
});

Introduction to PWAs

Progressive Web Apps are web applications that use modern web capabilities to deliver an app-like experience to users. They are reliable, fast, and engaging:

// Example manifest.json

{
  "name": "My PWA",
  "short_name": "PWA",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#4CAF50",
  "icons": [
    {
      "src": "icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}

Creating a PWA

To create a PWA, you need a manifest file and a service worker:

// Register service worker
if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js')
    .then(function(registration) {
        console.log('Service Worker registered with scope:', registration.scope);
    }).catch(function(error) {
        console.log('Service Worker registration failed:', error);
    });
}

Offline Caching

Use the Service Worker to cache assets for offline use:

// service-worker.js

self.addEventListener('install', function(event) {
    event.waitUntil(
        caches.open('my-cache').then(function(cache) {
            return cache.addAll([
                '/',
                '/index.html',
                '/styles.css',
                '/script.js'
            ]);
        })
    );
});

self.addEventListener('fetch', function(event) {
    event.respondWith(
        caches.match(event.request).then(function(response) {
            return response || fetch(event.request);
        })
    );
});

Introduction to Node.js

Node.js is a runtime environment that allows you to run JavaScript on the server-side:

// Install Node.js from https://nodejs.org/

// Create a new file app.js
const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    res.end('Hello World\n');
});

server.listen(port, hostname, () => {
    console.log(`Server running at http://${hostname}:${port}/`);
});

Using npm

npm (Node Package Manager) is used to install and manage packages:

// Initialize a new Node.js project
npm init -y

// Install a package
npm install express --save

Building a Simple Web Server

Use the Express framework to build a simple web server:

// Install Express
npm install express --save

// Create a new file app.js
const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
    res.send('Hello World!');
});

app.listen(port, () => {
    console.log(`Example app listening at http://localhost:${port}`);
});

Introduction to Testing

Testing is an important part of software development to ensure that your code works correctly. Use frameworks like Jest and Mocha for testing JavaScript applications:

// Install Jest
npm install --save-dev jest

// Add a test script to package.json
// "scripts": {
//   "test": "jest"
// }

// Create a test file sum.test.js
const sum = require('./sum');
test('adds 1 + 2 to equal 3', () => {
    expect(sum(1, 2)).toBe(3);
});

// Run the tests
npm test

Using Mocha

Mocha is another popular testing framework:

// Install Mocha
npm install --save-dev mocha

// Create a test file test.js
const assert = require('assert');
const sum = require('./sum');
describe('Sum', function() {
    it('should return 3 when 1 and 2 are added', function() {
        assert.equal(sum(1, 2), 3);
    });
});

// Run the tests
npx mocha

Introduction to Build Tools

Build tools like Webpack, Babel, and Gulp are used to automate tasks in the development workflow:

Webpack

Webpack is a static module bundler for modern JavaScript applications:

// Install Webpack
npm install --save-dev webpack webpack-cli

// Create a webpack.config.js file
module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: __dirname + '/dist'
    },
    mode: 'development'
};

// Add a build script to package.json
// "scripts": {
//   "build": "webpack"
// }

// Run the build
npm run build

Babel

Babel is a JavaScript compiler that allows you to use next-generation JavaScript, today. It transforms your ES6+ code into backwards compatible versions:

// Install Babel
npm install --save-dev @babel/core @babel/preset-env babel-loader

// Create a .babelrc file
{
  "presets": ["@babel/preset-env"]
}

// Update webpack.config.js to use Babel
module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: __dirname + '/dist'
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader'
                }
            }
        ]
    },
    mode: 'development'
};

// Run the build
npm run build

Gulp

Gulp is a toolkit for automating painful or time-consuming tasks in your development workflow:

// Install Gulp
npm install --save-dev gulp

// Create a gulpfile.js
const gulp = require('gulp');

gulp.task('hello', function(done) {
    console.log('Hello, world!');
    done();
});

// Run the Gulp task
npx gulp hello

Introduction to React

React is a JavaScript library for building user interfaces. It allows you to create reusable UI components:

// Install React
npx create-react-app my-app

// Change to the project directory
cd my-app

// Start the development server
npm start

Creating Components

Components are the building blocks of a React application:

// Create a new file src/Hello.js
import React from 'react';

function Hello(props) {
    return <h1>Hello, {props.name}!</h1>;
}

export default Hello;

// Use the component in src/App.js
import React from 'react';
import Hello from './Hello';

function App() {
    return (
        <div>
            <Hello name="World" />
        </div>
    );
}

export default App;

State and Props

State and props are used to manage data in React components:

import React, { useState } from 'react';

function Counter() {
    const [count, setCount] = useState(0);

    return (
        <div>
            <p>Count: {count}</p>
            <button onClick={() => setCount(count + 1)}>Increment</button>
        </div>
    );
}

export default Counter;

Introduction to Vue.js

Vue.js is a progressive JavaScript framework for building user interfaces. It is designed to be incrementally adoptable:

// Include Vue.js in your HTML file
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>

// Create a Vue instance
new Vue({
    el: '#app',
    data: {
        message: 'Hello, Vue!'
    }
});

Creating Components

Components are the building blocks of a Vue.js application:

<div id="app">
  <hello-world></hello-world>
</div>

<script>
Vue.component('hello-world', {
    template: '<h1>Hello, World!</h1>'
});

new Vue({
    el: '#app'
});
</script>

Reactive Data Binding

Vue.js uses reactive data binding to keep the DOM in sync with your data:

<div id="app">
  <p>{{ message }}</p>
  <input v-model="message">
</div>

<script>
new Vue({
    el: '#app',
    data: {
        message: 'Hello, Vue!'
    }
});
</script>

Introduction to Angular

Angular is a platform for building mobile and desktop web applications. It provides a comprehensive framework for building modern web applications:

// Install Angular CLI
npm install -g @angular/cli

// Create a new Angular project
ng new my-app

// Change to the project directory
cd my-app

// Start the development server
ng serve

Creating Components

Components are the building blocks of an Angular application:

// Generate a new component
ng generate component hello-world

// Use the component in app.component.html
<hello-world></hello-world>

// hello-world.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'hello-world',
  template: '<h1>Hello, World!</h1>',
})
export class HelloWorldComponent {}

Data Binding

Angular supports both one-way and two-way data binding:

// One-way data binding
<p>{{ message }}</p>

// Two-way data binding
<input [(ngModel)]="message">

// app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  message = 'Hello, Angular!';
}

Introduction to TypeScript

TypeScript is a superset of JavaScript that adds static types. It is designed for the development of large applications and transcompiles to JavaScript:

// Install TypeScript
npm install -g typescript

// Create a TypeScript file
// hello.ts
let message: string = 'Hello, TypeScript!';
console.log(message);

// Compile the TypeScript file
tsc hello.ts

Interfaces and Classes

TypeScript supports interfaces and classes for object-oriented programming:

// Define an interface
interface Person {
    name: string;
    age: number;
    greet(): string;
}

// Implement the interface in a class
class Student implements Person {
    constructor(public name: string, public age: number) {}

    greet() {
        return `Hello, my name is ${this.name} and I am ${this.age} years old.`;
    }
}

let student = new Student('John', 25);
console.log(student.greet());  // Hello, my name is John and I am 25 years old.

Generics

Generics provide a way to create reusable components:

function identity(arg: T): T {
    return arg;
}

let output1 = identity('Hello, Generics!');
let output2 = identity(42);

console.log(output1);  // Hello, Generics!
console.log(output2);  // 42