25 JavaScript Interview Questions for Testers (With Code)

These are the JavaScript questions automation testers are asked most — especially for Playwright, Cypress and API testing roles. The title promises 25, and here are all 25, grouped by topic, each with a short answer and code whose output has been verified in Node.js. For the full learning path, see The Complete JavaScript for Testers Guide.

Advertisement

Variables & Types (Q1–6)

1. What's the Difference Between var, let and const? ⭐

  • var is function-scoped, hoisted (initialized as undefined) and can be redeclared.
  • let is block-scoped and can be reassigned.
  • const is block-scoped and can't be reassigned.

Use const by default, let when a value must change, and avoid var in new code.

Learn more: Variables: var vs let vs const

2. Does const Make an Object Immutable?

No — it stops the variable being reassigned, but the object's properties can still change:

 
const user = { name: 'Asha' };

user.name = 'Ravi';        // allowed
// user = {};              // TypeError: Assignment to constant variable
 

Use Object.freeze() for a shallow read-only object.

3. What's the Difference Between == and ===?

== converts types before comparing; === compares value and type. Always prefer ===:

 
console.log(0 == false);    // true  (type coercion)
console.log(0 === false);   // false
 

4. null vs undefined?

undefined means a variable was declared but not assigned; null is an intentional "no value".

Note:

  • null == undefined is true
  • null === undefined is false
  • typeof null is "object"

The last one is a long-standing JavaScript quirk.

5. What Is Hoisting, and What Is the Temporal Dead Zone?

Declarations are moved to the top of their scope before code runs. var is hoisted and initialized to undefined; let and const are hoisted but not initialized.

Using let or const before the declaration throws a ReferenceError. This period is called the temporal dead zone.

 
console.log(y);   // undefined
var y = 2;

console.log(x);   // ReferenceError
let x = 1;
 

6. Which Values Are Falsy?

The following values are falsy:

  • false
  • 0
  • '' (empty string)
  • null
  • undefined
  • NaN
  • -0
  • 0n

Everything else is truthy — including [] and {}, which often surprises people when checking API responses.

Functions (Q7–11)

7. Function Declaration vs Arrow Function?

Function declarations are fully hoisted and get their own this.

Arrow functions are shorter, aren't hoisted like declarations, and take this from the surrounding scope. This is why they're common in Playwright tests and callbacks.

Learn more: Functions & Arrow Functions

8. What Is a Callback?

A callback is a function passed to another function to be called later.

For example, the function you pass to map() or setTimeout() is a callback.

Callbacks were the original way to handle asynchronous code before Promises became widely used.

9. What Are Default and Rest Parameters?

Default parameters provide fallback values, while rest parameters collect remaining arguments into an array.

 
function login(user, role = 'tester', ...tags) {
  return `${user} (${role}) ${tags.join(',')}`;
}

login('Asha');
// "Asha (tester) "

login('Ravi', 'admin', 'smoke', 'ui');
// "Ravi (admin) smoke,ui"
 

10. What Is a Closure? ⭐

A closure is a function that remembers variables from the scope where it was created, even after that scope has finished.

 
function counter() {
  let count = 0;

  return () => ++count;
}

const next = counter();

next();
console.log(next());   // 2 — count survives between calls
 

Closures are how private state and factory functions work — for example, a test-data generator that returns unique IDs.

11. What Does "this" Refer To?

It depends on how a function is called:

  • In a method call, this refers to the object before the dot.
  • In a regular standalone function, it is undefined in strict mode.
  • In an arrow function, this is inherited from the enclosing scope.

Page-object classes rely on this.page being the instance's page.

Arrays, Objects & JSON (Q12–17)

12. map() vs filter() vs forEach()? ⭐

map() returns a new, transformed array.

filter() returns the elements that match a condition.

forEach() simply loops through the elements and returns nothing.

 
const users = [
  { name: 'Asha', role: 'admin' },
  { name: 'Ravi', role: 'tester' }
];

users
  .filter(u => u.role === 'tester')
  .map(u => u.name);

// ['Ravi']
 

Learn more: Arrays & Objects

13. How Do You Find an Element in an Array?

JavaScript provides several useful methods:

  • find() returns the first matching element.
  • findIndex() returns its position.
  • includes() returns a boolean.
  • some() checks whether at least one element matches.
  • every() checks whether all elements match.
 
users.find(u => u.name === 'Asha').role;

// 'admin'
 

14. What Is Destructuring?

Destructuring means unpacking values from objects or arrays into variables.

It's common with API responses and Playwright fixtures.

 
const { name, role: userRole = 'none' } = {
  name: 'Asha'
};

console.log(name, userRole);

// Asha none

test('example', async ({ page }) => {
  // page is destructured from the fixtures
});
 

15. What's the Spread Operator? Is It a Deep Copy?

The ... spread operator expands arrays or objects.

It can be used for copying, merging or passing arguments.

However, it creates a shallow copy, not a deep copy. Nested objects are still shared.

 
const a = {
  n: {
    v: 1
  }
};

const b = { ...a };

b.n.v = 2;

console.log(a.n.v);

// 2 — the nested object was shared
 

For a deep copy of plain data, use:

 
structuredClone(a);
 

16. JSON vs a JavaScript Object?

JSON is a text format for storing and sending data. It uses double-quoted keys and does not support functions.

A JavaScript object is a live in-memory value.

Convert between them using:

 
JSON.parse(text);
JSON.stringify(obj);
 

Both are used constantly in API testing.

17. Why Does [10, 1, 5, 100].sort() Give the Wrong Order?

Without a comparator, sort() compares values as strings.

 
[10, 1, 5, 100].sort();

// [1, 10, 100, 5]

[10, 1, 5, 100].sort((a, b) => a - b);

// [1, 5, 10, 100]
 

This is a classic trap when asserting that a table is sorted by price.

Asynchronous JavaScript (Q18–23)

18. What Is a Promise?

A Promise is an object representing the eventual result of an asynchronous operation.

A Promise has one of three states:

  • Pending
  • Fulfilled
  • Rejected

Results can be handled with .then() / .catch() or await.

Learn more: Promises & Async/Await

19. What Is async/await? ⭐

async/await is syntax for writing Promise-based code that reads from top to bottom.

An async function always returns a Promise.

await pauses that function until the Promise settles.

 
test('login', async ({ page }) => {
  await page.goto('/login');

  await page
    .getByLabel('Email')
    .fill('asha@example.com');

  await page
    .getByRole('button', { name: 'Log in' })
    .click();
});
 

20. How Do You Handle Errors with async/await?

Use try...catch to handle errors from asynchronous operations.

 
try {
  const res = await fetch('https://api.example.com/users/1');

  if (!res.ok) {
    throw new Error(`HTTP ${res.status}`);
  }

  const user = await res.json();
} catch (err) {
  console.error('Request failed:', err.message);
}
 

21. What Happens If You Forget await in a Test?

The action starts, but the test doesn't wait for it.

As a result, the next step or assertion may execute too early — or the test may finish before the action completes.

This is a classic source of flaky tests.

Playwright's ESLint rules, such as no-floating-promises, can help catch this problem.

22. Promise.all vs Promise.allSettled?

Promise.all() fails as soon as any Promise rejects.

Promise.allSettled() waits for all Promises to finish and reports the result of each one.

 
const results = await Promise.allSettled([
  Promise.resolve(1),
  Promise.reject(new Error('x')),
]);

console.log(
  results.map(r => r.status)
);

// ['fulfilled', 'rejected']
 

Use allSettled() when you want every result — for example, when checking many links or API endpoints.

23. What's the Output Order? — Event Loop

Consider this example:

 
console.log('sync');

setTimeout(() => {
  console.log('timeout');
}, 0);

Promise.resolve().then(() => {
  console.log('microtask');
});

console.log('end');
 

The output is:

 
sync
end
microtask
timeout
 

The simplified execution order is:

  1. Synchronous code runs first.
  2. Promise callbacks (microtasks) run next.
  3. Timers such as setTimeout() run afterward.

Even a 0 ms timeout does not execute before the current synchronous code and microtasks.

JavaScript in Test Automation (Q24–25)

24. What Are ES Modules (import/export)?

ES modules are the standard way to split JavaScript code into multiple files.

Page objects and helpers can be exported from one file and imported where needed.

 
// pages/LoginPage.js
export class LoginPage {
  /* … */
}

// tests/login.spec.js
import { LoginPage } from '../pages/LoginPage';
 

25. Why Does JavaScript Matter for Testers?

JavaScript is important for automation testers because:

  • Playwright tests can be written in JavaScript or TypeScript.
  • Cypress uses JavaScript or TypeScript.
  • WebdriverIO supports JavaScript and TypeScript.
  • Postman test scripts use JavaScript.
  • Browser DevTools uses JavaScript.
  • Selenium's JavaScriptExecutor can execute JavaScript in the browser.

Understanding asynchronous code is particularly important because it can make the difference between stable and flaky automation tests.

Learn more: JavaScript for Playwright Automation

FAQs

How Much JavaScript Does an Automation Tester Need?

Variables and types, functions and arrow functions, arrays and objects, JSON, modules, and especially Promises and async/await — enough to write and debug Playwright, Cypress or Postman tests.

Which JavaScript Topics Are Asked Most in Testing Interviews?

Common topics include var/let/const, == vs ===, map()/filter(), async/await, Promises, closures and event-loop output questions.

Should Testers Learn JavaScript or TypeScript?

Learn JavaScript first. TypeScript adds static typing on top of JavaScript and is widely used in Playwright projects.

Is JavaScript Useful for Selenium Testers?

Yes. JavaScript is useful for JavaScriptExecutor, browser DevTools, Postman scripts, and moving from Selenium to Playwright or Cypress.

How Can I Practice?

Run the snippets above in Node.js or the browser console.

You can also practice with the Selenium Interview Simulator or the Playwright Interview Simulator.

Next Steps

 

From Real Projects

My automation background is Java with Selenium and TestNG. JavaScript comes up more and more for testers because tools like Playwright and Cypress are built on it — and most concepts on this page have a direct Java equivalent. Learning it alongside Java makes switching between frameworks much easier. Expect questions on async code — it's where most JavaScript test bugs come from.

📚 Official documentation: MDN: JavaScript Guide · dev.java: Learn Java (Oracle)