Sitemap
Bikramjit Roy

Bikramjit Roy

Full Stack Developer || DevOps Engineer

All About JavaScript

8 min readSep 30, 2026

--

Press enter or click to view image in full size

1. this keyword

Golden Rule: this depends on how the function is called, not where the function is written (arrow function is an exception)

Means if same function is called by different ways then it will become this . That’s why people get confused, so always focus on how the function is called ?

a. this in Global Scope (browser vs node)

In the browser, at the top level, this refers to the entire window object:

console.log(this); // window (the entire browser global object)

In Node.js (inside a .js file), every file is a module; therefore, at the top level, this is an empty object:

console.log(this); // {} (this is actually module.exports)

Note: In the Node REPL (accessed by simply typing node in the terminal), this refers to global, whereas inside a .js file, this is {} (module.exports). You will observe this difference if you test it in both environments.

1.2 — `this` in Regular Functions

function show() {
console.log(this);
}
show();
  • Browser (non-strict): this = window
  • Node (non-strict): this = global
  • In strict mode: this = undefined

Why? When you call a function directly like show() without an object, JavaScript assigns the default global object. This is called default binding.

1.3 — `this` in Methods

When a function is inside an object and called via that object:

const user = {
name: "Bikram",
greet() {
console.log("Hi, " + this.name);
}
};
user.greet(); // Hi, Bikram

Trick: “Look to the left of the dot — whatever is there, that is this.”

user.greet() → user is to the left of the dot → this = user.

Here is the catch (important demo):

const fn = user.greet; // extracted the reference, left the object behind
fn(); // undefined (now there is no object to the left of the dot)

It is the same function, but now there is no object to the left of the dot so this became the global object. This proves that this depends on “how it is called,” not “where it is written.”

1.4 — `this` in Arrow Functions (Lexical `this`)

An arrow function does not have its own this. It borrows this from its surroundings (enclosing scope). This is called lexical this.

const user = {
name: "Bikram",
greet: () => {
console.log(this.name); // undefined! (didn't take it from user)
}
};
user.greet();

However, this arrow function proves particularly useful in one specific scenario when dealing with nested callbacks:

const user = {
name: "Bikram",
hobbies: ["coding", "gaming"],
show() {
this.hobbies.forEach((hobby) => {
// The arrow function borrows 'this' from show()
console.log(this.name + " likes " + hobby);
});
}
};
user.show();
// Bikram likes coding
// Bikram likes gaming

Rule of thumb: Always define methods as regular functions (so that this points to the object), and use arrow functions for callbacks inside those methods (so that this is preserved).

1.5 — `this` in Event Handlers

In a regular function handler, this refers to the HTML element that triggered the event:

button.addEventListener("click", function () {
console.log(this); // The button element that was clicked
});

In an arrow function handler, this does not point to the element it points to the lexical scope (the window object):

button.addEventListener("click", () => {
console.log(this); // window (NOT the button)
});

Practical Tip: If you need access to the clicked element inside the handler, use a regular function or use event.target the latter works in both cases.

1.6 — `this` in Strict Mode

Using "use strict" makes JavaScript behave more strictly. The biggest change is:

"use strict";
function show() {
console.log(this); // undefined (in non-strict mode, it would be window)
}
show();

In non-strict mode, default binding points to the global object; in strict mode, it results in undefined. This is good it prevents accidental pollution of the global object. (ES6 modules and class bodies are automatically in strict mode.)

Quick Summary — `this` Cheatsheet

2. `call`, `apply`, `bind` Explicit Binding

Sometimes we want to decide for ourselves what `this` refers to. There are 3 methods for this known as explicit binding.

function introduce(city, country) {
console.log(`I am ${this.name}, from ${city}, ${country}`);
}
const person = { name: "Bikram" };

`call`: calls immediately, arguments separated by commas

introduce.call(person, "Kolkata", "India");
// I am Bikram, from Kolkata, India

First argument = value of `this`. Remaining arguments are standard comma separated values.

`apply` — call immediately, arguments in an ARRAY

introduce.apply(person, ["Kolkata", "India"]);
// I am Bikram, from Kolkata, India

Mnemonic: Apply = Array || Call = Comma. (A for A, C for C.)

`bind` do NOT call immediately; returns a new function

const boundFn = introduce.bind(person);
boundFn("Kolkata", "India");
// I am Bikram, from Kolkata, India

`bind` does not call the function immediately it returns a new function where `this` is permanently fixed (locked) to `person`. You can call it later whenever you want.

Real-world use: In event handlers and callbacks where the `this` context might get lost, `bind` is used to fix it permanently. For example: `setTimeout(introduce.bind(person), 1000)`.

3. Prototypes

3.1: What is a prototype?

Every JavaScript object contains a hidden link pointing to another object. That other object is called its prototype.

Benefit: If a property or method isn’t found in the object, JS looks for it in its prototype; if it’s not found there either, it checks the prototype’s prototype… and so on, moving up the chain. This chain is known as the prototype chain. Think of it like this: if a child can’t find something, they ask their father; if the father doesn’t have it, they ask the grandfather.

3.2: `__proto__` vs `prototype` (The most confusing pair)

Proof via code:

function Person(name) {
this.name = name;
}
const p = new Person("Bikram");
console.log(p.__proto__ === Person.prototype); // true

In a nutshell: `prototype` = a property of the function (blueprint for instances). `__proto__` = a property of the instance (the path to its blueprint). Connection: `instance.__proto__ === Function.prototype`.

Note: `__proto__` is considered “legacy” today (though it’s great for understanding concepts). In production code, `Object.getPrototypeOf(obj)` is used instead.

3.3: Prototype Chain

const arr = [1, 2, 3];
arr.push(4); // Where did push come from? It isn't defined inside arr!

JS searched like this:

  • In `arr` → didn’t find it
  • In `arr.__proto__` (which is `Array.prototype`) → found it!

arr → Array.prototype → Object.prototype → null

Get Bikramjit Roy’s stories in your inbox

Join Medium for free to get updates from this writer.

When it reaches `null` without finding the item → `undefined` is returned. This is the prototype chain.

3.4: `Object.create`

This method directly creates an object where you set the prototype yourself:

const animal = {
eats: true,
walk() { console.log("Animal is walking"); }
};
const dog = Object.create(animal); // dog's prototype = animal
dog.barks = true;
console.log(dog.barks); // true (its own)
console.log(dog.eats); // true (inherited from animal!)
dog.walk(); // Animal is walking

3.5: Inheritance via Prototypes

const vehicle = {
start() { console.log(this.name + " has started"); }
};
const car = Object.create(vehicle);
car.name = "Swift";
car.start(); // Swift has started

`car` inherited the `start` method from `vehicle`, and when the method ran, `this` referred to `car` (the “left-of-the-dot” rule!). That is why `this.name` became “Swift”. This is the core idea of ​​prototypal inheritance.

4. ES6 Classes

Understand first: new keyword comes with Class. When new MyClass() runs, JS does 4 things:

(1) a new empty object is created,

(2) its proto is set to class’s prototype,

(3) constructor runs in which this = that new object,

(4) that object automatically gets returned.

4.1: class Syntax + constructor + Instance Methods

class Person {
// this automatically gets called on running new
constructor(name, age) {
this.name = name;
this.age = age;
}
// instance method → automatically goes to prototype
greet() {
console.log("Hi, main " + this.name);
}
}

const p = new Person("Bikram", 27);
p.greet(); // Hi, I am Bikram

constructor → setup work (assign properties). methods like

greet() → automatically go to Person.prototype (copy is not created in every object — saves memory).

4.2 — Inheritance: extends & super

class Animal {
constructor(name) { this.name = name; }
eat() { console.log(this.name + " is eating"); }
}

class Dog extends Animal {
constructor(name, breed) {
super(name); // parent constructor call
this.breed = breed;
}
bark() { console.log(this.name + " bhonk raha hai"); }
}

const d = new Dog("Tommy", "Labrador");
d.eat(); // Tommy is eating (inherited from Animal)
d.bark(); // Tommy is barking (Dog's own)

extends → makes one class inherit from another.

super(name) → calls parent’s constructor.

⚠️ Rule: Calling super() before using this in child constructor is necessary, otherwise error. You can also call parent’s method using super.methodName().

4.3 — Static Methods & Static Properties static things are not on object, they are on class. These are not called from instance, but directly from class.

class MathHelper {
static PI = 3.14159; // static property
static add(a, b) { return a + b; } // static method
}

console.log(MathHelper.add(2, 3)); // 5 (call from class)
console.log(MathHelper.PI); // 3.14159

const m = new MathHelper();
// m.add(2, 3); → Error: static method is not on instance

📌 Real example: Array.isArray() is a static method. You don’t call it like [].isArray(), but like Array.isArray([]). Static is perfect for utility/helper functions.

4.4 — Getters & Setters

Through these we use a method like a property (without putting ()).

class Person {
constructor(first, last) {
this.first = first;
this.last = last;
}
get fullName() { // getter
return this.first + " " + this.last;
}
set fullName(value) { // setter
const parts = value.split(" ");
this.first = parts[0];
this.last = parts[1];
}
}

const p = new Person("Bikram", "Roy");
console.log(p.fullName); // Bikram Roy ((without ()!)
p.fullName = "Dipi Das"; // setter ran
console.log(p.first); // Dipi

Pay attention — wrote p.fullName, not p.fullName(). Getter/setter give feeling like property but logic runs inside. Very useful for validation (you can put check in setter).

4.5: Private Fields (#)

By applying # field cannot be accessed from outside only inside class.

class BankAccount {
#balance = 0; // private field

deposit(amount) { this.#balance += amount; }
getBalance() { return this.#balance; }
}

const acc = new BankAccount();
acc.deposit(500);
console.log(acc.getBalance()); // 500
// console.log(acc.#balance); → SyntaxError: no access from outside!

Only methods inside class can touch #balance. This gives encapsulation — saves important data from wrong changes.

4.6: Big Reveal: Classes are just Syntactic Sugar

“Class” is not any new thing in JavaScript. Inside it is that same old prototype + constructor function, just looks beautiful. This is called “syntactic sugar” — sweet packaging, same thing inside.

Proof 1 — Class is actually a function itself:

class Person {
constructor(name) { this.name = name; }
greet() { return "Hi " + this.name; }
}
console.log(typeof Person); // "function" (not class, function!)

Proof 2 — Methods went onto prototype itself:

console.log(typeof Person.prototype.greet); // "function"
// meaning greet method lies on Person.prototype - like old way

Proof 3 — Instance link is the same:

const p = new Person("Bikram");
console.log(p.__proto__ === Person.prototype); // true

Proof 4 — Exactly same thing in old way:

// This class...
class Person {
constructor(name) { this.name = name; }
greet() { return "Hi " + this.name; }
}

// ...is equal to exactly this constructor function:
function Person(name) {
this.name = name;
}
Person.prototype.greet = function () {
return "Hi " + this.name;
};

Behavior of both is 100% same. class is just an easy and clean way of writing inside, JavaScript is using prototype itself.

Remember: Next time you see any class, remember hidden behind is that same prototype that you studied in beginning. JavaScript has just dressed it in beautiful clothes.

--

--