JavaScript - Advanced Flashcards
What is the call() method?
The call method is used to invoke a function with a specified this value and arguments provided individually.
It takes the function’s this value as the first argument, followed by the function arguments.
function greet(name) {
console.log(Hello, ${name}! I am ${this.role}.
);
}
const person = {
role: ‘developer’,
};
greet.call(person, ‘John’);
What is the appy() method?
The apply method is similar to call, but it accepts arguments as an array or an array-like object.
The first argument is still the this value.
function greet(name) {
console.log(Hello, ${name}! I am ${this.role}.
);
}
const person = {
role: ‘developer’,
};
greet.apply(person, [‘John’]);
What is the bind() method?
The bind method returns a new function with the specified this value and partially applied arguments.
It does not immediately invoke the function but allows you to store it for later use.
function greet(name) {
console.log(Hello, ${name}! I am ${this.role}.
);
}
const person = {
role: ‘developer’,
};
const greetPerson = greet.bind(person);
greetPerson(‘John’);
What is the difference between the call(), apply() and bind() methods?
The main difference is that call and apply invoke the function immediately, whereas bind returns a new function that can be invoked later.
Explain the concept of lexical scoping?
Lexical scoping, also known as static scoping, is a scoping mechanism where the scope of a variable is determined by its location in the source code during the lexical phase of compilation.
In JavaScript, variables are scoped to the nearest enclosing block or function.
function outer() {
const x = 10;
function inner() {
console.log(x); // Accessible due to lexical scoping
}
inner();
}
outer();
In the example above, the inner function can access the variable x defined in its outer function due to lexical scoping.
Explain the concept of Dynamic Scoping?
Dynamic scoping is a scoping mechanism where the scope of a variable is determined by the current execution context or the calling stack.
In dynamic scoping, the scope chain is based on the runtime flow of the program.
Dynamic scoping is not natively supported in JavaScript, as it follows lexical scoping. However, you can simulate dynamic scoping behavior using the this context or by using the call or apply methods to change the execution context.
For example:
function outer() {
const x = 10;
function inner() {
console.log(this.x); // Accessible due to dynamic scoping (context-based)
}
inner.call({ x: 20 }); // Change the execution context dynamically
}
outer();
What is the key difference between Lexical Scoping and Dynamic Scoping?
lexical scoping is determined by the structure of the code, while dynamic scoping is based on the runtime context or calling stack.
What are the different ways to create classes in JavaScript?
Constructor Functions
ES6 Classes
Factory Functions
Constructor Functions
Constructor functions use the new keyword to create instances of an object with shared properties and methods.
They define properties and methods inside the constructor function using this.
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log(Hello, my name is ${this.name}.
);
};
const john = new Person(‘John’);
john.greet();
ES6 Classes
ES6 introduced a more concise syntax for creating classes using the class keyword. They provide a cleaner syntax for defining classes and their methods.
class Person {
constructor(name) {
this.name = name;
}
greet() {
console.log(Hello, my name is ${this.name}.
);
}
}
const john = new Person(‘John’);
john.greet();
Factory Functions
Factory functions are functions that return an object. They encapsulate the creation logic and allow you to create multiple instances with different internal states.
function createPerson(name) {
return {
name,
greet() {
console.log(Hello, my name is ${this.name}.
);
}
};
}
const john = createPerson(‘John’);
john.greet();
Explain the concept of memoization in JavaScript and how it can improve performance.
Memoization is a technique used to optimize function performance by caching the results of expensive function calls and returning the cached result when the same inputs occur again.
It aims to avoid redundant computations and improve overall execution speed.
function fibonacci(n, cache = {}) {
if (n in cache) {
return cache[n]; // Return cached result
}
if (n <= 2) {
return 1;
}
const result = fibonacci(n - 1, cache) + fibonacci(n - 2, cache);
cache[n] = result; // Cache the result for future use
return result;
}
console.log(fibonacci(10)); // 55
How does JavaScript handle memory management and garbage collection?
The garbage collector is responsible for managing memory allocation and deallocation to ensure efficient memory usage in JavaScript applications.
The process of garbage collection involves the following steps: marking, sweeping, memory compaction.
JavaScript’s garbage collector is typically implemented as a generational garbage collector. It divides objects into different generations based on their age. New objects are allocated in the “young” generation, and if they survive a certain number of garbage collection cycles, they are promoted to the “old” generation.
The garbage collector in JavaScript works transparently in the background, automatically reclaiming memory that is no longer in use. Developers do not need to explicitly free memory as it is managed by the JavaScript runtime environment.
Describe Garbage Collection Marking
The garbage collector traverses the entire object graph starting from the root objects (global objects, objects on the stack, etc.) and marks all the objects that are reachable or in use.
Describe Garbage Collection Sweeping
After marking, the garbage collector sweeps through the memory, deallocating or freeing the memory occupied by the objects that are not marked as reachable.
These objects are considered no longer needed and can be safely removed from memory.
Describe Garbage Collection Memory Compaction
Some garbage collectors may include an additional step of memory compaction, where the live objects are moved together to reduce memory fragmentation and optimize memory usage.
What is the purpose of the Proxy object in JavaScript?
The Proxy object in JavaScript is used to define custom behavior for fundamental operations (e.g., property access, assignment, function invocation) on an object.
It allows you to intercept and customize the default behavior of an object, providing a powerful mechanism for creating proxies with controlled access to underlying objects.
What are the steps of the event driven architecture as implemented in JavaScript?
Event Registration
Event Triggering
Event Loop
Event Handling
Repeat
Event Registration
JavaScript code registers event listeners or event handlers on specific elements or objects to listen for specific events. For example, adding a click event listener to a button.
Event Triggering
When an event occurs (e.g., a button is clicked, a timer expires, an HTTP request completes), the event is added to the event queue.