Programming Language
JavaScript
Introduction (Foundation)
Javascript Foundation

JavaScript Foundation

Introduction

  1. Why Learn Programming Languages?
    • Languages are used to write applications.
    • Developers write high-level code in these languages.
    • Compilers convert developer-friendly code into machine code (0s and 1s).

Compiled vs Interpreted Languages

  1. What are Compilers?

    • Compilers convert high-level code into machine code.
    • Example: The C++ compiler is called g++.
  2. Compiled Languages vs Interpreted Languages

    • Compiled Languages:
      1. Need to be compiled before running.
      2. Do not run if there is an error during compilation.
      3. Examples: C++, Java, Rust, Golang.
// Example in C++
#include <iostream>
 
int main() {
    std::cout << "Hello, World!" << std::endl;
    return 0;
}
// Compiled using: g++ example.cpp -o example
  • Interpreted Languages:
    1. Execute line by line.
    2. Can run partially even if there is an error later.
    3. Examples: JavaScript, Python.
// Example in JavaScript
console.log("Hello, World!");
// Interpreted directly in the browser or Node.js

Why JavaScript?

  1. Advantages of JavaScript
    • Primarily used for web development (frontend and backend).
    • Browsers can only understand HTML, CSS, and JavaScript.
    • With Node.js, JavaScript is also used for backend development.
// Example of JavaScript in the browser (frontend)
document.getElementById("myButton").addEventListener("click", function() {
    alert("Button clicked!");
});
 
// Example of JavaScript in Node.js (backend)
const http = require('http');
 
const server = http.createServer((req, res) => {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    res.end('Hello, World!\n');
});
 
server.listen(3000, '127.0.0.1', () => {
    console.log('Server running at http://127.0.0.1:3000/');
});
 

Static vs Dynamic Languages

  1. Dynamic Nature of TypeScript
  • Static typing means that the type of a variable is known at compile time. In statically typed languages, you must declare the type of variables, and the compiler checks for type consistency, which helps catch errors early.

Example in TypeScript

// Define a function with explicit types
function add(a: number, b: number): number {
    return a + b;
}
 
let result: number = add(5, 10);
console.log(result); // Output: 15
 
// TypeScript will throw an error if you try to assign a value of the wrong type
// let resultString: string = add(5, 10); // Error: Type 'number' is not assignable to type 'string'
  1. Dynamic Nature of JavaScript
    • JavaScript is a dynamically typed language.
    • Variables can hold any data type and can change types.
let dynamicVar = 42;       // Initially a number
dynamicVar = "Hello";     // Now a string
console.log(dynamicVar);  // Output: Hello
 

Single-threaded Nature of JavaScript

  1. Single-threaded Execution
    • JavaScript runs in a single thread.
    • Only one operation is executed at a time, making it seemingly unsuitable for scalable systems.
    • However, it can be optimized to use multiple cores.
console.log("First");
setTimeout(() => console.log("Second"), 0);
console.log("Third");
 
// Output order:
// First
// Third
// Second
 

Data Types in JavaScript

  1. Simple Primitives
    • Numbers, Strings, Booleans.
//    Numbers
   let age = 25;
let pi = 3.14;
 
// Strings
let name = "Alice";
let greeting = `Hello, ${name}!`; // Template literal
 
// Booleans
let isLoggedIn = true;
let hasAccess = false;
  1. Complex Primitives
  • Arrays, Objects.
  // Arrays
  let fruits = ["apple", "banana", "cherry"];
  console.log(fruits[1]); // Output: banana
 
  // Objects
   let person = {
   name: "Alice",
   age: 30,
   greet: function() {
   console.log(`Hello, my name is ${this.name}`);
   }
   };
   person.greet(); // Output: Hello, my name is Alice
 

Functions in JavaScript

A function in JavaScript is a set of statements that performs a task or calculates a value It should take some input and return an output where there is some obvious relationship between the input and the output.

  1. Purpose of Functions
    • Abstract out logic in the program.
    • Can take arguments and return values.
    • Functions can take other functions as arguments (callbacks).
// Basic function
function add(a, b) {
    return a + b;
}
console.log(add(2, 3)); // Output: 5
 
// Function as a callback
function greet(name, callback) {
    console.log("Hello, " + name);
    callback();
}
 
function sayGoodbye() {
    console.log("Goodbye!");
}
 
greet("Alice", sayGoodbye);
// Output:
// Hello, Alice
// Goodbye!
 

Asynchronous Programming in JavaScript

  1. Synchronous vs Asynchronous Functions

    • Synchronous Functions:
      • Execute line by line.
    • Asynchronous Functions:
      • Allow other operations to run while waiting for long-running operations to complete.
      • Essential in environments like web browsers or Node.js.
// Synchronous
console.log("Start");
console.log("End");
// Output:
// Start
// End
 
// Asynchronous
console.log("Start");
setTimeout(() => {
    console.log("Async operation completed");
}, 2000);
console.log("End");
 
// Output:
// Start
// End
// Async operation completed (after 2 seconds)
 
  1. Callback Functions, Event Loop, and Callback Queue

    • Callback Functions:
      • Functions passed as arguments to other functions.
    • Event Loop:
      • Handles asynchronous operations.
    • Callback Queue:
      • Queues callbacks for execution.
function fetchData(callback) {
    setTimeout(() => {
        console.log("Data fetched");
        callback();
    }, 2000);
}
 
fetchData(() => {
    console.log("Process data");
});
// Output:
// Data fetched (after 2 seconds)
// Process data
 
  1. Callback Hell and Promises
    • Callback Hell:
      • A situation where callbacks are nested within callbacks, making the code difficult to read and maintain.
    • Promises:
      • An alternative to callbacks for handling asynchronous operations.
// Example of Callback Hell
setTimeout(() => {
    console.log("First");
    setTimeout(() => {
        console.log("Second");
        setTimeout(() => {
            console.log("Third");
        }, 1000);
    }, 1000);
}, 1000);
 
// Example using Promises
const fetchData = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("Data fetched");
    }, 2000);
});
 
fetchData.then((message) => {
    console.log(message);
    return "Process data";
}).then((nextMessage) => {
    console.log(nextMessage);
});
// Output:
// Data fetched (after 2 seconds)
// Process data