Ankita.eth
GithubContact
  • About Ankita
  • experience
    • TECHNOLOGIES
    • Frontend
      • Javascript
      • React
      • NextJS
      • HTML & CSS
      • UI Libraries & Frameworks
        • Tailwind CSS
        • Comprehensive Guide to UI Libraries and Frameworks
    • Backend
      • Node.js
      • Express.js
    • Database
      • Mongodb, Mongoose
      • PostgresSQl
      • MySQL
    • Packege Mangers
      • NPM-Node Packege Manager
      • Yarn
      • Yarn 2 (Berry)
      • PNPM
      • BUN
      • Commands cheatsheet
    • API Providers
      • Alchemy
      • Telegram Bot
      • CoinMarket
      • Thirdweb
      • Infura
      • Moralis
    • DevOps/Infrastructure
      • Docker
      • Kubernetes
      • CI/CD
      • Docker Swam
    • Protocols
      • ERCs & EIPs
        • ERC-20
        • ERC-721
        • ERC-1155
        • ERC-4337
        • ERC-6551
        • ERC-777
        • ERC-3643
        • EIP-7702
        • ERC-7715
        • ERC-7739
        • EIP-6780
        • EIP-5792
        • ERC-4626
        • EIP-1559
        • ERC-404
        • ERC-3643
        • ERC-223
    • Web3 Toolkits
      • Foundry
      • Hardhat
      • RemixIDE
    • Messaging/Caching
      • Kafka
      • Redis
      • Sendgrid
    • Blockchain
      • Solana
      • Ethereum
      • Polygon & Zero knowldge Proof
      • Bitcoin
      • Solidity
    • Deployment Platforms
      • AWS
      • Vercel
      • Heroku, Render
      • Domain setup
  • SDKs
    • Google Cloud SDK
    • AWS SDK
    • Firebase SDK
  • EOF EVM Object Format
  • Articles
    • Medium Articles
    • 🌐 My Work
  • 📞 Get in Touch
Powered by GitBook
On this page
  • 📚 JavaScript Skills Overview
  • 🏗️ JavaScript Architecture
  • 🔠 Static vs Dynamic Typing in JavaScript
  • 🧠 Core JavaScript Concepts
  • 🌟 Real-Time Example: Building a Todo List
  • 🔍 Difference between var, let, and const
  • 🚀 ES6+ Features and Modern JavaScript Concepts
  • 🐞 Debugging Techniques for JavaScript

Was this helpful?

  1. experience
  2. Frontend

Javascript

PreviousFrontendNextReact

Last updated 9 months ago

Was this helpful?

JavaScript is a versatile, high-level programming language essential for creating dynamic and interactive web applications. Its capabilities span from front-end to back-end development, making it a cornerstone of modern web technology.

📚 JavaScript Skills Overview

This guide provides an overview of key JavaScript concepts and advanced topics, showcasing various coding examples and best practices.🚀

🏗️ JavaScript Architecture

JavaScript operates on a single-threaded, event-driven architecture, which allows for efficient handling of asynchronous operations.Here's a high-level overview:

This architecture allows JavaScript to handle asynchronous operations efficiently.

🔠 Static vs Dynamic Typing in JavaScript

JavaScript is a dynamically typed language, meaning variable types are determined at runtime. This flexibility can lead to runtime errors, but also enables more fluid coding. In contrast, statically typed languages like TypeScript require variable types to be declared at compile time, offering earlier error detection.

Here's an example illustrating dynamic typing in JavaScript:

let variable = 42;  // variable is a number
console.log(typeof variable);  // "number"

variable = "Hello, World!";  // Now variable is a string
console.log(typeof variable);  // "string"

variable = true;  // Now variable is a boolean
console.log(typeof variable);  // "boolean"

🧠 Core JavaScript Concepts

1. Variables and Data Types

JavaScript includes primitive types (like string, number, and boolean) and object types (like objects, arrays, and functions).

// Primitive types
let string = "Hello, World!";
let number = 42;
let boolean = true;
let nullValue = null;
let undefinedValue;
let symbol = Symbol("unique");

// Object types
let object = { key: "value" };
let array = [1, 2, 3];
let function = () => console.log("I'm a function!");

console.log(typeof string);  // "string"
console.log(typeof number);  // "number"
console.log(typeof boolean); // "boolean"
console.log(typeof nullValue); // "object" (this is a known quirk)
console.log(typeof undefinedValue); // "undefined"
console.log(typeof symbol);  // "symbol"
console.log(typeof object);  // "object"
console.log(typeof array);   // "object"
console.log(typeof function); // "function"

2. Functions and Scope

Functions are central in JavaScript, allowing for modular code. They can be declared using various syntaxes: traditional functions, function expressions, or arrow functions.

// Function declaration
function greet(name) {
    return `Hello, ${name}!`;
}

// Function expression
const farewell = function(name) {
    return `Goodbye, ${name}!`;
};

// Arrow function
const introduce = (name, age) => `I'm ${name} and I'm ${age} years old.`;

console.log(greet("Alice"));  // "Hello, Alice!"
console.log(farewell("Bob")); // "Goodbye, Bob!"
console.log(introduce("Charlie", 30)); // "I'm Charlie and I'm 30 years old."

// Demonstrating scope
//Scope in JavaScript can be global or local. Variables declared inside functions are local, while those outside are global.
let globalVar = "I'm global";

function demonstrateScope() {
    let localVar = "I'm local";
    console.log(globalVar);  // "I'm global"
    console.log(localVar);   // "I'm local"
}

demonstrateScope();
console.log(globalVar);  // "I'm global"
// console.log(localVar);   // ReferenceError: localVar is not defined

3. Object-Oriented Programming in JavaScript (OOP)

JavaScript supports OOP through prototype-based inheritance and class syntax.

// Constructor function (pre-ES6)
function Person(name, age) {
    this.name = name;
    this.age = age;
}

Person.prototype.greet = function() {
    console.log(`Hello, I'm ${this.name}`);
};

// Class syntax (ES6+)
class Animal {
    constructor(species) {
        this.species = species;
    }

    makeSound() {
        console.log("Some generic animal sound");
    }
}

class Dog extends Animal {
    constructor(name) {
        super("Canine");
        this.name = name;
    }

    makeSound() {
        console.log("Woof!");
    }
}

const person = new Person("Alice", 30);
person.greet();  // "Hello, I'm Alice"

const dog = new Dog("Buddy");
console.log(dog.species);  // "Canine"
dog.makeSound();  // "Woof!"

🌟 Real-Time Example: Building a Todo List

Let's create a simple todo list application to demonstrate various JavaScript concepts:

class TodoList {
    constructor() {
        this.todos = [];
    }

    addTodo(task) {
        this.todos.push({ task, completed: false });
    }

    toggleTodo(index) {
        this.todos[index].completed = !this.todos[index].completed;
    }

    removeTodo(index) {
        this.todos.splice(index, 1);
    }

    render() {
        const todoList = document.getElementById('todo-list');
        todoList.innerHTML = '';
        this.todos.forEach((todo, index) => {
            const li = document.createElement('li');
            li.textContent = todo.task;
            if (todo.completed) {
                li.style.textDecoration = 'line-through';
            }
            li.addEventListener('click', () => {
                this.toggleTodo(index);
                this.render();
            });
            const removeButton = document.createElement('button');
            removeButton.textContent = 'Remove';
            removeButton.addEventListener('click', (e) => {
                e.stopPropagation();
                this.removeTodo(index);
                this.render();
            });
            li.appendChild(removeButton);
            todoList.appendChild(li);
        });
    }
}

const todoList = new TodoList();

document.getElementById('add-todo').addEventListener('click', () => {
    const input = document.getElementById('todo-input');
    if (input.value) {
        todoList.addTodo(input.value);
        input.value = '';
        todoList.render();
    }
});

todoList.render();

🔍 Difference between var, let, and const

Understanding variable declaration is crucial in JavaScript:

  1. var is function-scoped and can be redeclared and updated. Its hoisting behavior can cause unexpected results.

  2. let is block-scoped and allows for reassigning but not redeclaration.

  3. const is also block-scoped but cannot be reassigned or redeclared.

Here's an example illustrating the differences:

// var
var x = 1;
if (true) {
    var x = 2;  // Same variable!
    console.log(x);  // 2
}
console.log(x);  // 2

// let
let y = 1;
if (true) {
    let y = 2;  // Different variable
    console.log(y);  // 2
}
console.log(y);  // 1

// const
const z = 1;
// z = 2;  // Error: Assignment to a constant variable
console.log(z);  // 1

Why var is not recommended:

  • Lack of block scoping can lead to unexpected behavior and bugs

  • Hoisting can cause confusion and make code harder to reason about

  • Allows for redeclaration, which can lead to accidental overwrites

Using let and const provides better control over variable scope and mutability, leading to cleaner and more predictable code. It's generally recommended to use const by default, and let when you need to reassign a variable. var should be avoided in modern JavaScript development unless you have a specific reason to use it.

🚀 ES6+ Features and Modern JavaScript Concepts

JavaScript has evolved significantly since the introduction of ECMAScript 2015 (ES6). Let's explore some core concepts and features of modern JavaScript:

1. 🏹 Arrow Functions

Arrow functions provide a concise syntax for writing function expressions:

// Traditional function
function add(a, b) {
  return a + b;
}

// Arrow function
const add = (a, b) => a + b;

// Arrow function with implicit return
const square = x => x * x;

2. 🎭 Destructuring

Destructuring allows you to unpack values from arrays or properties from objects into distinct variables, making it easier to work with complex data structures.

// Array destructuring
const [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first, second, rest); // 1 2 [3, 4, 5]

// Object destructuring
const { name, age } = { name: 'Alice', age: 30, country: 'USA' };
console.log(name, age); // Alice 30

3. 📦 Spread and Rest Operators

The spread operator (...) can be used to expand elements, while the rest operator can collect multiple elements into an array:

// Spread operator
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5];
console.log(arr2); // [1, 2, 3, 4, 5]

// Rest operator
function sum(...numbers) {
  return numbers.reduce((acc, curr) => acc + curr, 0);
}
console.log(sum(1, 2, 3, 4)); // 10

4. 🏷️ Template Literals

Template literals allow for easy string interpolation and multiline strings:

const name = 'Alice';
const greeting = `Hello, ${name}!
Welcome to ES6+.`;
console.log(greeting);
// Hello, Alice!
// Welcome to ES6+.

5. 🔄 Asynchronous Programming

Modern JavaScript provides several ways to handle asynchronous operations:

5.1 Promises

function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Data fetched successfully');
    }, 2000);
  });
}

fetchData()
  .then(data => console.log(data))
  .catch(error => console.error(error));

5.2 Async/Await

async function getData() {
  try {
    const result = await fetchData();
    console.log(result);
  } catch (error) {
    console.error(error);
  }
}

getData();

Callbacks

Callbacks are functions passed as arguments to other functions, executed after a certain task is completed. They are the foundation of asynchronous programming in JavaScript but can lead to complex code structures known as "callback hell."

function fetchData(callback) {
    setTimeout(() => {
        callback("Data fetched");
    }, 1000);
}

fetchData((data) => {
    console.log(data); // Output: Data fetched
});

Here's a visual representation of asynchronous operations:

6. 🏛️ Object-Oriented Programming

JavaScript supports object-oriented programming through prototypes and classes, enabling you to create reusable and scalable code structures.

Prototypes

Prototypes allow JavaScript to implement inheritance, enabling objects to share properties and methods. This model provides a way to extend objects and create shared behavior across instances.

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

Person.prototype.greet = function() {
    console.log(`Hello, my name is ${this.name}`);
};

const person1 = new Person("Alice");
person1.greet(); // Output: Hello, my name is Alice

Classes

Classes offer a more structured and intuitive syntax for defining objects and their behaviors. They simplify the creation of complex applications by organizing code into modular, reusable components.

class Animal {
  constructor(name) {
    this.name = name;
  }
  
  speak() {
    console.log(`${this.name} makes a sound.`);
  }
}

class Dog extends Animal {
  speak() {
    console.log(`${this.name} barks.`);
  }
}

const dog = new Dog('Rex');
dog.speak(); // Rex barks.

7. 🌳 DOM Manipulation

JavaScript allows you to manipulate the Document Object Model (DOM) to create interactive web pages. This capability is fundamental for updating and managing the content and structure of web pages dynamically.

// Creating elements
const div = document.createElement('div');
div.textContent = 'Hello, World!';
document.body.appendChild(div);

// Querying elements
const button = document.querySelector('#myButton');
button.addEventListener('click', () => {
  console.log('Button clicked!');
});

// Modifying styles
const element = document.getElementById('myElement');
element.style.backgroundColor = 'blue';
element.classList.add('highlight');

8. 🐛 Error Handling and Debugging

JavaScript development involves dealing with errors and debugging to ensure code reliability and functionality.

Understanding Errors and Exceptions

JavaScript uses error objects to represent exceptional circumstances in your code. These can be created using the Error constructor or its subclasses like TypeError, ReferenceError, or SyntaxError.

throw new Error("This is a custom error message.");

Try, Catch, and Finally Blocks

Use try, catch, and finally blocks to handle exceptions and ensure code executes correctly even when errors occur.

try {
  // Code that might throw an exception
} catch (error) {
  // Code to handle the exception
} finally {
  // Code to be executed regardless of whether an exception was thrown
}

Custom Error Handling

Create custom error types for more specific error handling by extending the built-in Error class.

class CustomError extends Error {
  constructor(message) {
    super(message);
    this.name = "CustomError";
  }
}

try {
  throw new CustomError("This is a custom error.");
} catch (error) {
  if (error instanceof CustomError) {
    console.error("Caught a CustomError:", error.message);
  } else {
    console.error("Caught an unknown error:", error.message);
  }
}

These modern JavaScript features and concepts provide powerful tools for building efficient, readable, and maintainable code. As you continue to explore and practice, you'll find even more ways to leverage these capabilities in your projects. 🚀👨‍💻

🐞 Debugging Techniques for JavaScript

Here are some powerful debugging techniques to help you troubleshoot your JavaScript code, along with code snippets:

  • 🖨️ Console Logging: Use console.log(), console.warn(), and console.error() to output values and messages.

// Basic console logging
console.log('Debug value:', someVariable);

// Styled console logging
console.log('%cDebug', 'color: blue; font-weight: bold;', 'Value:', someVariable);

// Warning and Error logging
console.warn('Warning: Something might be wrong');
console.error('Error: Something went wrong');
  • 🔍 Debugger Statement: Insert debugger; in your code to pause execution and inspect variables.

function troublesomeFunction() {
  let x = 5;
  debugger; // Execution will pause here
  x = x * 2;
  return x;
}
  • 🔬 Browser DevTools: Utilize breakpoints, watch expressions, and the console in your browser's developer tools.

  • 🔄 Try-Catch Blocks: Wrap potentially problematic code in try-catch blocks to handle and log errors gracefully.

try {
  // Potentially problematic code
  let result = riskyFunction();
  console.log('Result:', result);
} catch (error) {
  console.error('An error occurred:', error.message);
}
  • 📊 Performance Profiling: Use console.time() and console.timeEnd() to measure code execution time.

console.time('Loop time');
for(let i = 0; i < 1000000; i++) {
  // Some operation
}
console.timeEnd('Loop time');
  • 🔢 Stack Trace Analysis: Examine the call stack to understand the sequence of function calls leading to an error.

function firstFunction() {
  secondFunction();
}

function secondFunction() {
  thirdFunction();
}

function thirdFunction() {
  console.trace('Trace at thirdFunction');
  throw new Error('An error occurred');
}

try {
  firstFunction();
} catch (error) {
  console.error('Error Stack:', error.stack);
}
  • 🧪 Unit Testing: Implement unit tests using frameworks like Jest or Mocha to catch bugs early.

// Using Jest
test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});

function sum(a, b) {
  return a + b;
}
  • 🔄 Source Maps: Use source maps to debug minified or transpiled code in its original form.

  • 🧹 Use Linters and Formatters: Integrate tools like ESLint and Prettier to maintain consistent code style and catch potential issues early.

// .eslintrc.json
{
  "extends": ["eslint:recommended", "plugin:prettier/recommended"],
  "rules": {
    "no-console": "warn",
    "semi": ["error", "always"],
    "quotes": ["error", "single"]
  },
  "env": {
    "browser": true,
    "node": true
  }
}

Using linters and formatters can significantly improve code quality and consistency across your project. They help catch common errors and enforce a uniform coding style, making your codebase more maintainable and easier to read.