80% of JavaScript interviews Flashcards

1
Q

What is the difference between var, let, and const?

A

In JavaScript, var, let, and const are used to declare variables, but they differ in scope, hoisting, and mutability:

  1. var:
    • Scope: Function-scoped or globally scoped if declared outside a function. Not block-scoped.
    • Hoisting: Variables are hoisted to the top of their function or global scope and initialized with undefined, allowing use before declaration.
    • Reassignment: Can be reassigned and redeclared within the same scope.
    • Example:
      javascript
      var x = 5;
      var x = 10; // Redeclaration allowed
      console.log(x); // 10
  2. let:
    • Scope: Block-scoped (limited to the block {} where it’s defined).
    • Hoisting: Hoisted to the top of the block but not initialized, causing a “Temporal Dead Zone” (TDZ) until the declaration is reached.
    • Reassignment: Can be reassigned but cannot be redeclared in the same scope.
    • Example:
      javascript
      let y = 5;
      y = 10; // Reassignment allowed
      // let y = 15; // Error: redeclaration not allowed
      console.log(y); // 10
  3. const:
    • Scope: Block-scoped, like let.
    • Hoisting: Hoisted but not initialized, also subject to TDZ.
    • Reassignment: Cannot be reassigned or redeclared after initialization. However, for objects and arrays, their properties or elements can be modified.
    • Example:
      javascript
      const z = 5;
      // z = 10; // Error: reassignment not allowed
      const obj = { a: 1 };
      obj.a = 2; // Allowed: modifying object property
      console.log(obj); // { a: 2 }

Key Differences:
- Use var for legacy code (pre-ES6), but it’s prone to errors due to hoisting and lack of block scope.
- Use let for variables that need reassignment.
- Use const for variables that should not be reassigned, promoting immutability.

As an SDET, I’d ensure tests cover scenarios like variable scope, hoisting behavior, and immutability to catch bugs related to incorrect usage.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Explain hoisting in JavaScript with examples.

A

Your Response:

“Hoisting is a JavaScript behavior where variable and function declarations are moved to the top of their scope—either global or function scope—during compilation, but initializations stay in place.

For example, with var:

console.log(x); // Outputs undefined
var x = 5;//⬅️ initializations

Here, var x is hoisted and initialized as undefined, so it’s accessible but not yet assigned.

With let or const, it’s different:

console.log(y); // ReferenceError
let y = 10;

let y is hoisted but not initialized, creating a Temporal Dead Zone until the declaration, so accessing it early throws an error.

Function declarations are fully hoisted:

sayHello(); // Outputs "Hello!"
function sayHello() { console.log("Hello!"); }

The entire function is available before its declaration.

As an SDET, I’d write tests to catch hoisting-related bugs, like accessing variables before initialization, and recommend using let or const to avoid var’s unpredictable hoisting behavior.”

Tips for Delivery:
1. Be Concise: This response is short (~1 minute) but covers the essentials. Avoid over-explaining unless prompted.
2. Use Examples: Briefly show code or describe scenarios to prove you understand the concept practically.
3. Relate to SDET Role: Mention testing or code quality to tie it to your expertise, showing you think like a quality engineer.
4. Stay Confident: Speak clearly and pause slightly after key points to ensure clarity.
5. Adapt to Follow-Ups: If asked for more details (e.g., function expressions or TDZ), expand with:
- “Function expressions, like var func = function() {}, only hoist the variable, not the function, so calling it early causes a TypeError.”
- “The Temporal Dead Zone ensures let and const are safer by preventing access before initialization.”

Practice Version for Confidence:
Practice this a few times to sound natural:
“Hoisting moves declarations to the top of their scope. For var, it’s initialized as undefined, like console.log(x); var x = 5; logging undefined. For let or const, it’s hoisted but in a Temporal Dead Zone, so console.log(y); let y = 10; throws a ReferenceError. Functions hoist fully, so sayHello(); function sayHello() {} works. As an SDET, I’d test these edge cases to catch bugs and prefer let/const for safer code.”

This keeps you sounding professional, relevant, and ready for deeper questions!

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

What are closures in JavaScript?

A

A closure in JavaScript is when a function retains access to variables from its outer (enclosing) scope, even after that outer scope has finished executing. It’s like a function carrying a ‘backpack’ of its surrounding variables.

For example:

function outer() {
  let count = 0;
  return function inner() {
    count++;
    console.log(count);
  };
}
const counter = outer();
counter(); // Outputs 1
counter(); // Outputs 2

Here, inner forms a closure over count. Even after outer finishes, inner remembers and updates count each time it’s called.

Closures are useful for data privacy, like creating private variables, or for things like event handlers and callbacks. As an SDET, I’d test closures to ensure variables maintain their state correctly and there are no memory leaks from unintended references.”

Why This Works:
- Clear and Concise: Explains the concept in ~30-40 seconds with a simple analogy (“backpack”).
- Practical Example: The counter example shows how closures work in real code.
- SDET Relevance: Ties it to testing, showing you understand practical implications.
- Engaging: Invites follow-up questions (e.g., memory leaks, use cases) without overloading.

If Prompted for More:
- Use Case: “Closures are great for creating factory functions or encapsulating state, like in module patterns.”
- Testing Angle: “I’d write tests to verify the inner function accesses the correct outer variables and check for memory issues in long-running apps.”

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Explain the difference between shallow copy and deep copy.

A

“A shallow copy creates a new object or array, but only copies the top-level properties or elements. If those properties are objects or arrays, it copies their references, not the nested data. So, changes to nested objects affect both the original and the copy.

A deep copy, on the other hand, creates a completely independent copy of the object, including all nested objects and arrays. Changes to the copy don’t affect the original.

For example:

// Shallow copy
const original = { name: 'Alice', details: { age: 25 } };
const shallow = { ...original };
shallow.details.age = 30;
console.log(original.details.age); // Outputs 30 (original is affected)

// Deep copy
const deep = JSON.parse(JSON.stringify(original));
deep.details.age = 35;
console.log(original.details.age); // Outputs 30 (original is unchanged)

Shallow copies are faster but risk unintended side effects with nested data. Deep copies ensure independence but can be slower for large objects. As an SDET, I’d test shallow vs. deep copy behavior to ensure data integrity and catch bugs from shared references.”

Why This Works:
- Clear Definition: Distinguishes shallow and deep copies concisely.
- Practical Example: Shows the difference with code, making it tangible.
- SDET Tie-In: Highlights testing for data integrity, relevant to the role.
- Concise: Delivers in ~40 seconds, leaving room for follow-ups.

If Prompted for More:
- Shallow Copy Methods: “Shallow copies can be made with Object.assign(), spread operator (...), or Array.slice().”
- Deep Copy Limitations: “JSON-based deep copies don’t handle functions or special objects like Dates. Libraries like Lodash offer robust deep cloning.”
- Testing Angle: “I’d write unit tests to verify that deep copies don’t mutate the original and check performance for large datasets.”

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

What is prototypal inheritance, and how does it work?

A

“Prototypal inheritance is JavaScript’s mechanism for objects to inherit properties and methods from other objects via their prototype chain. Every object has a __proto__ property linking to its prototype, which allows it to access properties or methods defined on that prototype.

For example:

const parent = { greet: () => console.log('Hello') };
const child = Object.create(parent);
child.greet(); // Outputs 'Hello'
Here, child inherits greet from parent through the prototype chain. If a property isn’t found on child, JavaScript looks up the chain.

As an SDET, I’d test prototype methods to ensure they behave as expected and verify the chain isn’t unintentionally modified, which could break inheritance.”

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

What is the difference between Object.create() and class-based inheritance?

A

“Object.create() is a method to create a new object with a specified prototype, enabling prototypal inheritance directly. Class-based inheritance, introduced in ES6, uses the class syntax to define a blueprint for objects, but under the hood, it still uses prototypes.

For example:

// Object.create
const parent = { greet: () => 'Hello' };
const child = Object.create(parent);
console.log(child.greet()); // Hello

// Class-based
class Parent {
  greet() { return 'Hello'; }
}
class Child extends Parent {}
const child2 = new Child();
console.log(child2.greet()); // Hello

Object.create() is lightweight and explicit for linking prototypes, while class offers a structured, syntactic sugar approach for inheritance. As an SDET, I’d test both to ensure inherited methods work and check for proper prototype chain behavior.”

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

What are getter and setter functions in JavaScript?

A

“Getters and setters are special methods in JavaScript that allow controlled access to an object’s properties. A getter retrieves a property’s value, while a setter defines how a property is set, often with validation.

For example:

const person = {
  _age: 25,
  get age() { 
return this._age; 
},
  set age(value) { 
if (value >= 0) 
this._age = value; }
};
console.log(person.age); // 25
person.age = 30; // Sets _age to 30
person.age = -5; // Ignored due to validation

As an SDET, I’d test getters to ensure they return correct values and setters to verify validation logic prevents invalid updates.”

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

How does this keyword work in JavaScript?

A

“The this keyword in JavaScript refers to the object that is executing the current function, and its value depends on how the function is called.

For example:

Copy
const obj = {
  name: 'Alice',
  greet: function() { console.log(this.name); }
};
obj.greet(); // Outputs 'Alice' (this is obj)
const func = obj.greet;
func(); // Outputs undefined (this is global/window in non-strict mode)

this can also be set explicitly with call(), apply(), or bind(). In arrow functions, this is lexically bound to the enclosing scope. As an SDET, I’d test this behavior across contexts, like event handlers or callbacks, to catch bugs from incorrect bindings.”

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

What is the difference between call(), apply(), and bind()?

A

call(), apply(), and bind()are methods to control the value of this in a function and pass arguments.

call(): Invokes the function immediately, setting this and passing arguments individually.
apply(): Like call(), but passes arguments as an array.
bind(): Returns a new function with this permanently set, without invoking it immediately.
For example:

function greet(greeting) { console.log(`${greeting}, ${this.name}`); }
const person = { name: 'Alice' };

greet.call(person, 'Hi'); // Outputs: Hi, Alice
greet.apply(person, ['Hello']); // Outputs: Hello, Alice
const boundGreet = greet.bind(person);
boundGreet('Hey'); // Outputs: Hey, Alice

As an SDET, I’d test these methods to ensure this is correctly bound and arguments are passed as expected, especially in complex callback scenarios.”

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

What is the difference between == and === in JavaScript?

A

== is the loose equality operator, which compares values after performing type coercion, converting operands to the same type.
===is the strict equality operator, which compares both value and type without coercion.

For example:

console.log(5 == '5'); // true (string '5' coerced to number)
console.log(5 === '5'); // false (different types)

As an SDET, I’d test edge cases with == to catch bugs from unexpected coercion, like null == undefined being true, and advocate for === to ensure predictable behavior.”

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

How does the event loop work in JavaScript?

A
  1. How does the event loop work in JavaScript?
    Response:

“The event loop is JavaScript’s mechanism for handling asynchronous operations in its single-threaded environment. It continuously checks the call stack and task queue. If the call stack is empty, it takes tasks from the queue (like callbacks or async operations) and pushes them to the stack for execution.

For example:

console.log('Start');
setTimeout(() => console.log('Timeout'), 0);
console.log('End');
// Outputs: Start, End, Timeout

Even with a 0ms delay, setTimeout goes to the task queue, and the event loop processes it after the synchronous code.

As an SDET, I’d test async code to ensure callbacks execute in the correct order and verify no race conditions occur.”

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

What are promises and how do they work?

A

“A promise is an object representing the eventual completion or failure of an asynchronous operation. It has three states: pending, fulfilled, or rejected. Promises allow chaining with .then() for success and .catch() for errors.

For example:

const promise = new Promise((resolve, reject) => {
  setTimeout(() => resolve('Success'), 1000);
});
promise.then(result => console.log(result)); // Outputs 'Success' after 1s
promise.catch(error => console.log(error));

As an SDET, I’d write tests to verify promise resolution, error handling, and chaining behavior to ensure robust async workflows.”

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

What is async/await, and how is it different from promises?

A

“async/await is syntactic sugar built on top of promises to make asynchronous code look synchronous and easier to read. An async function returns a promise, and await pauses execution until the promise resolves.

For example:

async function fetchData() {
  try {
    const result = await new Promise(resolve => setTimeout(() => resolve('Data'), 1000));
    console.log(result); // Outputs 'Data' after 1s
  } catch (error) {
    console.log(error);
  }
}
fetchData();

Compared to promises, async/await avoids chaining .then() and makes error handling cleaner with try/catch. As an SDET, I’d test await behavior for correct resolution and ensure errors are caught properly.”

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

What is memoization, and how can it be implemented in JavaScript?

A

“Memoization is an optimization technique where the results of expensive function calls are cached and reused when the same inputs occur again, reducing computation time.

For example:

function memoize(fn) {
  const cache = {};
  return function (...args) {
    const key = JSON.stringify(args);
    if (cache[key]) return cache[key];
    cache[key] = fn(...args);
    return cache[key];
  };
}
const slowFunction = (num) => {
  // Simulate expensive computation
  return num * 2;
};
const memoized = memoize(slowFunction);
console.log(memoized(5)); // Computes and caches: 10
console.log(memoized(5)); // Uses cache: 10

As an SDET, I’d test memoized functions to ensure cache hits return correct results and verify performance improvements for repeated calls.”

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

What are higher-order functions, and can you give an example?

A

“A higher-order function is a function that either takes another function as an argument, returns a function, or both. They’re powerful for abstraction and code reuse.

For example:

const numbers = [1, 2, 3];
const double = num => num * 2;
const doubledNumbers = numbers.map(double); // map is a higher-order function
console.log(doubledNumbers); // Outputs [2, 4, 6]

Here, map takes the double function as an argument. As an SDET, I’d test higher-order functions to ensure the passed functions produce correct outputs and handle edge cases like empty arrays.”

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Delivery Tips for the Interview:
Be Concise: Each answer is ~30-40 seconds, fitting well in an interview setting.
Use Examples: Brief code snippets make your answers concrete and demonstrate understanding.
SDET Focus: Mention testing (e.g., edge cases, performance, error handling) to align with the role.
Stay Confident: Practice these to deliver smoothly. Pause slightly after key points for clarity.
Handle Follow-Ups: If asked for more, expand briefly (e.g., “For promises, I could also test race conditions with Promise.all”).
Practice Strategy:
Rehearse each answer aloud 2-3 times to sound natural.
Focus on one question at a time, then combine them to simulate a rapid-fire Q&A.
If nervous, start with a simple structure: “It’s [definition]. For example, [code]. As an SDET, I’d test [relevance].”
These responses should help you shine in an SDET interview by showing technical depth and testing awareness!

A

Delivery Tips for the Interview:
Be Concise: Each answer is ~30-40 seconds, fitting well in an interview setting.
Use Examples: Brief code snippets make your answers concrete and demonstrate understanding.
SDET Focus: Mention testing (e.g., edge cases, performance, error handling) to align with the role.
Stay Confident: Practice these to deliver smoothly. Pause slightly after key points for clarity.
Handle Follow-Ups: If asked for more, expand briefly (e.g., “For promises, I could also test race conditions with Promise.all”).
Practice Strategy:
Rehearse each answer aloud 2-3 times to sound natural.
Focus on one question at a time, then combine them to simulate a rapid-fire Q&A.
If nervous, start with a simple structure: “It’s [definition]. For example, [code]. As an SDET, I’d test [relevance].”
These responses should help you shine in an SDET interview by showing technical depth and testing awareness!