JavaScript Interview Questions 11-15 (Inheritance, Classes, call/apply/bind, Generators, Callbacks)
Welcome to Part 3 of our JavaScript interview preparation series. We are now stepping into intermediate territory. These topics often determine how well you understand the "architecture" of JavaScript—how objects share functionality, how to manually control context, and how to handle complex function flows.
We will cover prototypal inheritance(the heart of JS objects), classes(the modern syntax), the trio of call, apply, and bind, magic pausable functions called generators, and the foundation of asynchronous code: callbacks. Relax, take a deep breath, and let's break these down simply.
11. What is prototypal inheritance?
JavaScript doesn't use "classical" inheritance like Java or C++ (where classes are blueprints). Instead, it uses prototypes. Every object in JavaScript has a hidden link to another object called its prototype. When you try to access a property that doesn't exist on the object itself, JavaScript looks up the chain to the prototype to find it. This chain continues until it reaches null.
Analogy: Think of it like a family heirloom. If you need a vintage watch and you don't have one, you ask your parent. If they don't have one, they ask their parent (your grandparent). You "inherit" access to the watch through this chain of connections.
const parent = {
greet: function() {
return "Hello from the parent!";
}
};
// Create a child object that inherits from parent
const child = Object.create(parent);
child.name = "Junior";
// The child doesn't have 'greet', so it looks up the chain
console.log(child.name); // "Junior" (Found on child)
console.log(child.greet()); // "Hello from the parent!" (Found on parent)
Sample Output:
Junior
Hello from the parent!
12. What are JavaScript classes?
Classes, introduced in ES6 (2015), are essentially "syntactic sugar" over JavaScript's existing prototypal inheritance. They provide a cleaner, more readable syntax that looks like traditional Object-Oriented Programming (OOP) languages, but under the hood, they still work via prototypes.
- Constructor: A special method for initializing new objects.
- Extends: Used to create a child class (inheritance).
- Super: Used to call the parent class's constructor or methods.
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + " makes a noise.");
}
}
class Dog extends Animal {
speak() {
console.log(this.name + " barks!");
}
}
const d = new Dog("Rex");
d.speak(); // Uses the overridden method in Dog
Sample Output:
Rex barks!
13. What is the difference between call, apply, and bind?
These are three methods located on the Function prototype that allow you to manually control what the keyword this refers to. They are often used when you want to "borrow" a method from one object and use it with another.
| Method | Execution | Arguments |
|---|---|---|
| Call | Immediate | Passed individually (comma separated) |
| Apply | Immediate | Passed as an Array [arg1, arg2] |
| Bind | Delayed (Returns a new function) | Passed individually |
Analogy:
Call: You call a friend and ask them to help move a couch right now.
Apply: You apply for a job right now, but you submit your documents in a single folder (array).
Bind: You sign a contract (bind) guaranteeing you will do the job later, locking in the details.
const person = {
fullName: function(city, country) {
console.log(this.firstName + " " + this.lastName + ", " + city + ", " + country);
}
};
const person1 = {
firstName: "John",
lastName: "Doe"
};
// 1. Call (arguments separated by commas)
person.fullName.call(person1, "Oslo", "Norway");
// 2. Apply (arguments in an array)
person.fullName.apply(person1, ["Oslo", "Norway"]);
// 3. Bind (returns a new function to use later)
const boundFunction = person.fullName.bind(person1, "Oslo", "Norway");
console.log("--- Wait for it ---");
boundFunction();
Sample Output:
John Doe, Oslo, Norway
John Doe, Oslo, Norway
--- Wait for it ---
John Doe, Oslo, Norway
14. What are generators in JavaScript?
Regular functions run from top to bottom and cannot be stopped. Generators are special functions that can pause their execution and resume later. They are defined using an asterisk function* and use the yield keyword to pause.
Analogy: A regular function is like a roller coaster ride; once it starts, you can't get off until the end. A generator is like reading a book; you can read a page, put a bookmark (yield) in, go do something else, and come back later to resume exactly where you left off.
function* simpleGenerator() {
yield 1;
yield 2;
yield 3;
}
const generator = simpleGenerator();
// .next() resumes execution until the next yield
console.log(generator.next()); // { value: 1, done: false }
console.log(generator.next()); // { value: 2, done: false }
console.log(generator.next()); // { value: 3, done: false }
console.log(generator.next()); // { value: undefined, done: true }
Tip: Generators are powerful for handling data streams or implementing custom iterators where you don't want to compute all values at once (lazy evaluation).
Sample Output:
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ value: undefined, done: true }
15. What are callbacks in JavaScript?
A callback is simply a function passed as an argument into another function, which is then executed (called back) inside the outer function to complete some kind of routine or action. They are the primary way JavaScript handles asynchronous operations, like reading files or fetching data from a server, ensuring code doesn't run before the data is ready.
Analogy: Imagine you order a custom pizza. You give the cashier your phone number (the callback). You don't stand at the counter staring at the oven. You go sit down. When the pizza is ready, they call your number (execute the callback) so you can come get it.
function fetchData(callback) {
console.log("1. Fetching data...");
// Simulate a 2-second delay (like a server request)
setTimeout(() => {
const data = { id: 1, user: "Alice" };
console.log("2. Data arrived!");
callback(data); // Execute the callback now that data is ready
}, 2000);
}
function processData(data) {
console.log("3. Processing data for: " + data.user);
}
// Pass 'processData' into 'fetchData'
fetchData(processData);
Sample Output:
1. Fetching data...
// (waits 2 seconds)
2. Data arrived!
3. Processing data for: Alice
You have successfully navigated through five sophisticated JavaScript concepts! Understanding prototypes and inheritance sets you apart as someone who knows the language deep down. Mastering context (this) and async flow (callbacks) shows you can handle real-world application logic. Keep practicing these patterns, and you will feel much more relaxed during your technical discussions.