JavaScript Interview Questions (Free Preview)
Free sample of 15 from 150 questions available
Definitions pt. 1
What is a closure?
A closure is an inner function that has access to:
a) Its own local variables,
b) Variables in the outer function’s scope, and
c) Global variables.
In the example below, the function add10 is a closure (inner function) of the function add (outer function). Even
though add10(20) and add10(50) are called with only one parameter, the closure returns the correct result because
the value 10 (defined in the outer function’s scope) is preserved at the time add(10) is called.
const add = x => y => x + y;
const add10 = add(10);
console.log(add10(20)); // 30
console.log(add10(50)); // 60
↑ Back to top
What is the Event Loop?
The Event Loop is the mechanism that manages the execution of tasks from the call stack, the task queue, and the render queue. Every function invocation is placed on the call stack. When an asynchronous function creates a callback, it is added to the task queue. Meanwhile, operations that affect the visual rendering of the page (e.g., style changes, layout recalculations, DOM updates) are placed in the render queue.
In summary, the Event Loop performs the following cycle:
- Execute all tasks in the call stack.
- Execute all pending operations in the render queue that alter the page (e.g., style updates, layout recalculations, DOM manipulations).
- Check the task queue; if it contains any tasks and the call stack is empty, take one task from the task queue and push it onto the call stack.
How does hoisting work?
Hoisting is a JavaScript mechanism that moves declarations of functions and variables to the top of their containing scope (either function scope or global scope). It is important to note that only declarations are hoisted, not the definitions.
var x = 1; // initialization of x
console.log(x + ' ' + y); // '1 undefined'
var y = 2; // initialization of y
For the interpreter, this is equivalent to:
var x = 1; // initialization of x
var y; // declaration of y
console.log(x + ' ' + y); // '1 undefined'
y = 2; // initialization of y
↑ Back to top
What is prototypal inheritance?
Prototypal inheritance is a mechanism by which objects inherit properties and methods from other objects (their "parents"). The prototype is an object that serves as a template for creating other objects.
function Animal(name) {
this.name = name;
}
function Dog(name) {
// When creating a Dog, the Animal constructor is invoked
Animal.call(this, name);
}
// Dog inherits from Animal
Dog.prototype = Object.create(Animal.prototype);
Animal.prototype.getName = function () {
return 'Hello, ' + this.name;
}
// Although 'name' is stored in Animal, Dog has access to it
var dog = new Dog('Husky');
console.log(dog.getName()); // 'Hello, Husky'
↑ Back to top
What is scope?
Scope is the domain within a program where variables are visible and accessible. It depends on how they are declared.
By using the let keyword, variables are declared using block scope. This means the variable is only accessible
within the block in which it is declared.
The const keyword is used to declare constants. Their scope is the same as variables declared with let, with the
main difference being that once a value is assigned to a const, it cannot be altered.
The var keyword allows defining variables that remain accessible within the entire function, even if they are declared
inside a block. Their scope is limited to the function (known as function scope) or the global context if declared
outside of any function.
JavaScript API pt. 1
What is the difference between == and ===?
The double equal sign (==) performs equality comparison between two expressions or values. Before comparing, it
attempts to convert them to the same type. In contrast, the triple equal sign (===) checks for both value and type
equality without performing any type conversion.
| x | y | x == y | x === y |
|---|---|---|---|
| 5 | 5 | true | true |
| 1 | '1' | true | false |
| null | undefined | true | false |
| 0 | false | true | false |
| '1,2' | [1,2] | true | false |
What is the Difference Between let and var?
The primary difference lies in the scope where the variable is declared:
vardeclares a variable with function scope.letdeclares a variable with block scope.
Moreover, while all variable declarations are hoisted, only variables declared with var are automatically
initialized to undefined. In contrast, let (and const) declarations remain uninitialized until their actual
declaration is evaluated, which can lead to a ReferenceError when they are accessed before initialization.
function saveCourse(courseData) {
if (courseData) {
console.log(maxStudents); // Outputs: undefined
console.log(courseLength); // Throws ReferenceError
var maxStudents = 12; // function-scoped
let courseLength = 30; // block-scoped
}
console.log(maxStudents); // Outputs: 12
console.log(courseLength); // Throws ReferenceError
}
↑ Back to top
What Distinguishes null from undefined?
In JavaScript, undefined indicates that a variable has been declared but has not been assigned a value yet. For
example:
let courseLength;
console.log(courseLength); // undefined
console.log(typeof courseLength); // "undefined"
On the other hand, null is a value that can be explicitly assigned to a variable to indicate "no value":
let courseContent = null;
console.log(courseContent); // null
console.log(typeof courseContent); // "object"
console.log(null === undefined); // false
console.log(null == undefined); // true
↑ Back to top
What Distinguishes call() from apply()?
The call() and apply() functions are used to change the execution context of a function, i.e., to redefine the
this pointer—allowing a function defined in one object to be executed in the context of another.
- The
apply()function invokes a function by passing a giventhisvalue and an array of arguments:
const numbers = [1, 2], others = [3, 4];
numbers.push.apply(numbers, others);
console.log(numbers); // [1, 2, 3, 4]
- Conversely, the
call()function accepts arguments as individual values:
const numbers = [1, 2], others = [3, 4];
numbers.push.call(numbers, ...others);
console.log(numbers); // [1, 2, 3, 4]
↑ Back to top
What is the Spread Operator?
The spread operator allows you to expand an expression where multiple arguments (for function calls), several array elements (when creating arrays), or multiple variables are needed.
const results = [5, 5, 4];
function calculateResults(a, b, c) {
return a + b + c;
}
calculateResults(5, 5, 4); // 14
calculateResults(...results); // 14
const courses = ["Vue", "React", "Angular"];
const [firstCourse, ...allTheRest] = courses;
console.log(firstCourse); // "Vue"
console.log(allTheRest); // ["React", "Angular"]
console.log([...firstCourse]); // ["V", "u", "e"]
↑ Back to top
Asynchronous Code
What is a Promise?
A Promise is an object representing the result of an asynchronous operation. It can be in one of three states: fulfilled (completed),rejected (failed), or pending (in progress).
An asynchronous task can finish with:
- success – in which case the
resolve()function is called - failure – in which case
reject()is called
function asyncOperation() {
return new Promise((resolve, reject) => {
// asynchronous task...
resolve(/* result */);
});
}
↑ Back to top
What is async/await?
Async/await provides a simpler syntax for writing and handling asynchronous functions built on top of Promise.
The async keyword before a function declaration ensures that it returns a Promise by default.
The await keyword forces the asynchronous operation (typically a Promise) on its right-hand side to complete before
continuing with the subsequent part of the function.
Note that await can only be used within an async function; otherwise, an exception will be thrown.
async function findUserMessages(username) {
const user = await findUserData(username);
const messages = await findMessages(user.id);
return messages;
}
↑ Back to top
Browser API
What is Event Bubbling?
Event Bubbling is a type of event propagation where events are initially handled by the **most deeply nested element
** and subsequently processed by each of its parent elements up the DOM tree. The addEventListener() function
allows registering an event listener for a specified event type. The third parameter of this function, useCapture,
controls whether event propagation is handled using event bubbling (default) or event capturing. Event Bubbling
can be stopped by calling event.stopPropagation().
element.addEventListener('click', handle, false);
// useCapture = false, handling bubbling
↑ Back to top
Functions pt. 1
What Are Higher-Order Functions?
Higher-order functions are functions that operate on other functions. Specifically, these functions either:
- Accept a function as an argument, or
- Return a function as the result of their execution.
Common examples of higher-order functions include map(), filter(), and reduce(). In the example below,
greaterThan() is a higher-order function that accepts a limit and returns another function which checks if a given
number is greater than that limit:
const greaterThan = limit =>
number => number > limit;
const greaterThan10 = greaterThan(10);
console.log(greaterThan10(20)); // true
↑ Back to top
HTTP
What Is CORS?
CORS, or Cross-Origin Resource Sharing, is a mechanism that allows applications running on one origin to access resources hosted on a different origin. For example, a request from https://fiszkijs.pl to https://www.googleapis.com/gmail/v1/ is considered a cross-origin request.
For security reasons, browsers block such requests by default. To enable them, the server receiving the request must
include the header Access-Control-Allow-Origin: * or, preferably, a more restricted header such as
Access-Control-Allow-Origin: https://fiszkijs.pl in its response.