🚀 JavaScript Fundamentals (Week-03): Understanding the Concepts That Every Developer Should Know

"Writing JavaScript code is one thing, but understanding what happens behind the scenes is what makes you a better developer."

When I first started learning JavaScript, I knew how to declare variables and write functions. However, I often found myself asking questions like:

  • Why are there three ways to declare variables?
  • What exactly is hoisting?
  • How does JavaScript execute my code?
  • Why can an inner function access variables from its parent function?
  • What does the this keyword actually refer to?
  • Why do developers keep talking about writing clean code?

This week, I focused on understanding these core JavaScript concepts instead of simply memorizing syntax.

In this article, I'll explain each concept in a beginner-friendly way with examples and practical explanations.


📚 Topics Covered

  • Variables (var, let, const)
  • Hoisting
  • Lexical Scope
  • Execution Context
  • Call Stack
  • Closures
  • this Binding
  • DRY Principle
  • KISS Principle

Let's start from the beginning.


📦 Variables in JavaScript

What is a Variable?

A variable is a named container used to store data in memory.

Instead of writing the same value repeatedly, we store it inside a variable and reuse it whenever required.

For example,

let name = "Sai";

console.log(name);

Enter fullscreen mode Exit fullscreen mode

Output

Sai

Enter fullscreen mode Exit fullscreen mode

Here,

  • let → Variable declaration keyword
  • name → Variable name
  • "Sai" → Stored value

Why Do We Need Variables?

Imagine writing this:

console.log("Sai");
console.log("Sai");
console.log("Sai");

Enter fullscreen mode Exit fullscreen mode

If the value changes, every occurrence must be updated.

Using variables,

let name = "Sai";

console.log(name);
console.log(name);
console.log(name);

Enter fullscreen mode Exit fullscreen mode

Now changing one line updates every usage.

Variables improve:

  • Readability
  • Reusability
  • Maintainability

Types of Variables

JavaScript provides three ways to declare variables.

  • var
  • let
  • const

Although all three create variables, they behave differently.


var

var was introduced in the first version of JavaScript.

Characteristics:

  • Function Scoped
  • Can be redeclared
  • Can be reassigned
  • Hoisted

Example

var city = "Hyderabad";

var city = "Bangalore";

console.log(city);

Enter fullscreen mode Exit fullscreen mode

Output

Bangalore

Enter fullscreen mode Exit fullscreen mode

Because var allows redeclaration, it can accidentally overwrite existing values.


let

let was introduced in ES6.

Characteristics

  • Block Scoped
  • Cannot be redeclared
  • Can be reassigned

Example

let age = 20;

age = 21;

console.log(age);

Enter fullscreen mode Exit fullscreen mode

Output

21

Enter fullscreen mode Exit fullscreen mode


const

const is used when the variable should not be reassigned.

Characteristics

  • Block Scoped
  • Cannot be redeclared
  • Cannot be reassigned
const PI = 3.14;

console.log(PI);

Enter fullscreen mode Exit fullscreen mode

Output

3.14

Enter fullscreen mode Exit fullscreen mode


📈 Hoisting

What is Hoisting?

Hoisting is JavaScript's behavior of processing declarations before executing the code.

This doesn't mean the code physically moves. Instead, during the memory creation phase, JavaScript prepares variables and functions before execution begins.

Example

console.log(language);

var language = "JavaScript";

Enter fullscreen mode Exit fullscreen mode

Output

undefined

Enter fullscreen mode Exit fullscreen mode

Internally JavaScript treats it like this:

var language;

console.log(language);

language = "JavaScript";

Enter fullscreen mode Exit fullscreen mode

Variables declared using let and const are also hoisted, but they remain inside the Temporal Dead Zone (TDZ) until they are initialized.


🌍 Lexical Scope

Scope determines where a variable can be accessed.

Lexical Scope means an inner function can access variables declared in its outer function because of where it is written.

Example

function outer(){

    let message="Hello";

    function inner(){

        console.log(message);

    }

    inner();

}

outer();

Enter fullscreen mode Exit fullscreen mode

Output

Hello

Enter fullscreen mode Exit fullscreen mode

JavaScript first searches inside inner(). If the variable isn't found, it looks in the outer function.

This searching process is called the Scope Chain.


⚙️ Execution Context

Before JavaScript executes any code, it creates an Execution Context.

Think of it as JavaScript's workspace.

It stores:

  • Variables
  • Functions
  • Scope
  • Value of this

Every Execution Context has two phases.

Memory Creation Phase

During this phase,

  • Variables are allocated memory.
  • var variables are initialized with undefined.
  • Function declarations are stored.

Execution Phase

During this phase,

  • Variables receive values.
  • Statements execute one by one.
  • Function calls create new execution contexts.

📚 Call Stack

The Call Stack keeps track of function execution.

It follows the Last In, First Out (LIFO) principle.

Example

function first(){

    second();

}

function second(){

    console.log("Inside Second");

}

first();

Enter fullscreen mode Exit fullscreen mode

Output

Inside Second

Enter fullscreen mode Exit fullscreen mode

Execution Flow

first()



second()



console.log()



Return



Return

Enter fullscreen mode Exit fullscreen mode


🔒 Closures

One of JavaScript's most powerful features is the Closure.

A Closure is created when an inner function remembers variables from its outer function even after the outer function has finished execution.

Example

function counter(){

    let count = 0;

    return function(){

        count++;

        console.log(count);

    }

}

const increment = counter();

increment();

increment();

increment();

Enter fullscreen mode Exit fullscreen mode

Output

1
2
3

Enter fullscreen mode Exit fullscreen mode

Closures are commonly used for:

  • Counters
  • Data Privacy
  • Event Handlers
  • Module Pattern

🎯 Understanding this

The this keyword refers to the object that calls a function.

Its value depends on how the function is called.

Implicit Binding

const user = {

    name:"Sai",

    greet(){

        console.log(this.name);

    }

}

user.greet();

Enter fullscreen mode Exit fullscreen mode

Output

Sai

Enter fullscreen mode Exit fullscreen mode


Explicit Binding

JavaScript provides call(), apply(), and bind() to explicitly decide what this should refer to.

function greet(){

    console.log(this.name);

}

const user={

    name:"Sai"

};

greet.call(user);

Enter fullscreen mode Exit fullscreen mode

Output

Sai

Enter fullscreen mode Exit fullscreen mode


new Binding

function Student(name){

    this.name=name;

}

const s1=new Student("Sai");

console.log(s1.name);

Enter fullscreen mode Exit fullscreen mode

Output

Sai

Enter fullscreen mode Exit fullscreen mode


Arrow Function

Arrow functions don't have their own this.

Instead, they inherit it from their surrounding scope.


✨ DRY Principle

DRY stands for

Don't Repeat Yourself

Instead of repeating code,

console.log("Welcome Sai");

console.log("Welcome Rahul");

Enter fullscreen mode Exit fullscreen mode

write

function greet(name){

    console.log(`Welcome ${name}`);

}

greet("Sai");

greet("Rahul");

Enter fullscreen mode Exit fullscreen mode

Benefits

  • Reusable code
  • Easy maintenance
  • Less duplication

💡 KISS Principle

KISS stands for

Keep It Simple, Stupid

Simple code is easier to understand than complicated code.

Instead of

function isEven(num){

    if(num%2===0){

        return true;

    }

    else{

        return false;

    }

}

Enter fullscreen mode Exit fullscreen mode

write

function isEven(num){

    return num%2===0;

}

Enter fullscreen mode Exit fullscreen mode

Simple code is:

  • Easy to debug
  • Easy to maintain
  • Easy to understand

🎯 Key Takeaways

After completing this week's learning, I understood that:

  • Variables store data.
  • Hoisting happens during memory creation.
  • Lexical Scope decides where variables are accessible.
  • Execution Context provides the environment for code execution.
  • The Call Stack manages function execution.
  • Closures preserve variables after a function finishes.
  • The value of this depends on how a function is called.
  • Following DRY and KISS helps write clean and maintainable code.

📝 Conclusion

Learning JavaScript isn't just about writing code—it's about understanding how the language works behind the scenes. Concepts like execution context, scope, closures, and this binding explain why our code behaves the way it does. By combining these fundamentals with clean coding principles like DRY and KISS, we can write code that is not only correct but also easy to read, maintain, and extend.