Skip to main content

Last updated: May 2026

Practice Exam

JS-Dev-101Salesforce Certified JavaScript Developer I

Test your knowledge with official exam-style questions

Questions25Passing65Exam time105 min

Questions and options are shuffled each attempt

Salesforce Certified JavaScript DeveloperPractice Exam Set 1: All Questions & Explanations

Full question text, answer options, and explanations for this practice set — a spoiler-free alternative is the interactive quiz above for scored, shuffled practice.

  1. 1. What is the output of the following JavaScript code? ```javascript console.log(typeof null); ```

    • A. 'null'
    • B. 'object'(correct)
    • C. 'undefined'
    • D. 'boolean'

    Explanation: typeof null returns 'object' — this is a well-known bug in JavaScript that has been present since its initial implementation and is preserved for backward compatibility. The value null is a primitive representing intentional absence of value, but typeof incorrectly reports it as 'object'. This is an important JavaScript quirk to know for the exam.

  2. 2. What is the difference between `let` and `var` in JavaScript?

    • A. `let` is function-scoped; `var` is block-scoped
    • B. `let` is block-scoped and not hoisted to the top of its scope in a usable state; `var` is function-scoped and hoisted with `undefined`(correct)
    • C. There is no difference; both are interchangeable
    • D. `let` cannot be reassigned; `var` can be reassigned

    Explanation: `var` is function-scoped (or global if declared outside a function) and is hoisted to the top of its function with an initial value of `undefined`. `let` is block-scoped (limited to the enclosing `{}` block) and is hoisted but not initialized — accessing it before its declaration causes a ReferenceError (the 'Temporal Dead Zone'). Using `let` and `const` instead of `var` is modern JavaScript best practice for predictable scoping.

  3. 3. What does the following code output? ```javascript const a = [1, 2, 3]; const b = [...a, 4, 5]; console.log(b); ```

    • A. [1, 2, 3]
    • B. [[1, 2, 3], 4, 5]
    • C. [1, 2, 3, 4, 5](correct)
    • D. Error: cannot spread a const array

    Explanation: The spread operator (`...`) expands an iterable (array, string, etc.) into individual elements. `[...a, 4, 5]` creates a new array by spreading the elements of `a` (1, 2, 3) followed by the additional elements 4 and 5, resulting in [1, 2, 3, 4, 5]. `const` prevents reassignment of the variable `a` but does not make the array immutable or prevent its elements from being spread.

  4. 4. Which two statements about JavaScript's `===` (strict equality) vs `==` (loose equality) are correct? (Choose 2)

    • A. `===` compares both value and type without type coercion(correct)
    • B. `==` performs type coercion before comparison, so `'5' == 5` is `true`(correct)
    • C. `===` performs type coercion for primitive comparisons
    • D. `null == undefined` is `false` with `==`

    Explanation: `===` (strict equality) compares value AND type without any coercion: `'5' === 5` is `false` because one is string and one is number. `==` (loose equality) performs type coercion: `'5' == 5` is `true` because the string '5' is coerced to number 5. Additionally, `null == undefined` is `true` with `==` (they are considered equal by loose equality). Using `===` is strongly recommended to avoid unexpected coercion bugs.

  5. 5. What is the output of this code? ```javascript const obj = { a: 1, b: 2, c: 3 }; const { a, ...rest } = obj; console.log(rest); ```

    • A. { a: 1, b: 2, c: 3 }
    • B. { b: 2, c: 3 }(correct)
    • C. [2, 3]
    • D. { a: undefined, b: 2, c: 3 }

    Explanation: Object destructuring with the rest parameter (`...rest`) collects all remaining properties that were not destructured into a new object. `const { a, ...rest } = obj` extracts `a` (value 1) and assigns the remaining properties (b: 2, c: 3) to `rest`. So `rest` is `{ b: 2, c: 3 }`. This is the object rest syntax, analogous to the array rest parameter.

  6. 6. Which two Array methods return a NEW array without modifying the original? (Choose 2)

    • A. .map()(correct)
    • B. .push()
    • C. .filter()(correct)
    • D. .splice()

    Explanation: `.map()` and `.filter()` are non-mutating array methods that return new arrays: `.map()` transforms each element and returns a new array of the same length; `.filter()` returns a new array containing only elements that pass the test function. `.push()` adds elements to the END of the original array (mutates it). `.splice()` removes, replaces, or inserts elements in the original array (mutates it). This immutability distinction is critical in modern JavaScript development.

  7. 7. What does this code output? ```javascript const person = { name: 'Alice', greet() { return `Hello, ${this.name}`; } }; const greet = person.greet; console.log(greet()); ```

    • A. 'Hello, Alice'
    • B. 'Hello, undefined'(correct)
    • C. TypeError
    • D. 'Hello, '

    Explanation: When a method is extracted from an object and called without the object context (`greet()` instead of `person.greet()`), `this` inside the function refers to `undefined` in strict mode, or the global object (`window`) in non-strict mode. In non-strict mode, `window.name` is typically an empty string or undefined, so `${this.name}` resolves to `undefined` (or empty string). This is the classic `this` binding problem in JavaScript — the context is lost when the method is detached from its object.

  8. 8. What is a closure in JavaScript?

    • A. A function that closes the browser window
    • B. A function that retains access to its outer scope's variables even after the outer function has returned(correct)
    • C. A way to prevent a function from being called more than once
    • D. The process of converting an object to a JSON string

    Explanation: A closure is a function that 'closes over' variables from its outer (lexical) scope, retaining access to those variables even after the outer function has finished executing. For example, a factory function that returns an inner function — the inner function can still access the factory's local variables through the closure. Closures are fundamental to JavaScript and are used extensively in modules, callbacks, and event handlers.

  9. 9. What is the difference between an arrow function and a regular function regarding `this`?

    • A. Arrow functions have their own `this` bound dynamically; regular functions inherit `this` from the enclosing scope
    • B. Arrow functions do not have their own `this`; they inherit `this` lexically from the enclosing scope; regular functions have a dynamic `this` based on how they are called(correct)
    • C. Arrow functions and regular functions behave identically with respect to `this`
    • D. Arrow functions bind `this` to the global object; regular functions bind to `undefined`

    Explanation: Arrow functions do NOT have their own `this`. They capture `this` lexically from the enclosing scope at the time of definition. Regular functions have a dynamic `this` determined by HOW they are called (method call, function call, new, call/apply/bind). This makes arrow functions ideal for callbacks inside methods where you want to preserve the outer `this` (e.g., `setTimeout(() => this.update(), 1000)`).

  10. 10. Which two statements about JavaScript classes are true? (Choose 2)

    • A. JavaScript classes are syntactic sugar over prototype-based inheritance(correct)
    • B. A child class constructor must call `super()` before accessing `this`(correct)
    • C. Class declarations are hoisted like function declarations, so they can be used before they are defined
    • D. Private class fields (prefixed with #) are accessible from subclasses

    Explanation: JavaScript classes (introduced in ES6) are syntactic sugar over the existing prototype-based inheritance model — they don't introduce a new OOP paradigm. In subclasses, `super()` must be called in the constructor before `this` is accessed, or a ReferenceError is thrown. Class declarations (unlike function declarations) are NOT hoisted in a usable way — they are in the Temporal Dead Zone until evaluated. Private fields (`#field`) are truly private and NOT accessible from subclasses.

  11. 11. What is a JavaScript generator function and what does `yield` do?

    • A. A generator is a function that generates random numbers; `yield` returns the generated number
    • B. A generator (function*) is a function that can be paused and resumed; `yield` pauses execution and returns a value, with execution resuming on the next `.next()` call(correct)
    • C. A generator is a constructor function; `yield` is an alias for `return`
    • D. Generators are deprecated in modern JavaScript; use async/await instead

    Explanation: Generator functions (declared with `function*`) create generator objects. When called, they don't execute the body immediately; instead, they return a generator object. Each call to `.next()` on the generator runs the body until the next `yield` expression, pausing execution and returning the yielded value. Generators enable lazy evaluation, infinite sequences, and custom iterators. They are not deprecated — async/await actually builds on generator concepts.

  12. 12. What does `Object.freeze()` do in JavaScript?

    • A. It makes an object's properties immutable — existing properties cannot be changed, added, or deleted(correct)
    • B. It converts an object to a frozen (unmodifiable) JSON string
    • C. It prevents an object from being passed as a function argument
    • D. It deeply freezes an object and all nested objects recursively

    Explanation: `Object.freeze()` makes an object's properties immutable at the shallow level: existing properties cannot be added, deleted, or modified. Attempting to modify a frozen object in strict mode throws a TypeError; in non-strict mode, the operation silently fails. Importantly, `Object.freeze()` is SHALLOW — nested objects (object property values) are not frozen. For deep immutability, a recursive freeze implementation is needed.

  13. 13. In JavaScript, what is event bubbling?

    • A. When a user event causes multiple browser windows to open
    • B. When an event triggered on a child element propagates up through the DOM to parent elements(correct)
    • C. When event listeners are added to all parent elements automatically
    • D. When events are queued in a bubble memory buffer before processing

    Explanation: Event bubbling is the process where an event triggered on a specific element (e.g., a button click) propagates up through the DOM tree to its parent elements, then their parents, up to the document root. Each ancestor element's event listeners for the same event type will also fire unless `stopPropagation()` is called. Event delegation (attaching listeners to a parent to handle child events) relies on bubbling.

  14. 14. Which method prevents an event from bubbling up to parent elements?

    • A. event.preventDefault()
    • B. event.stopPropagation()(correct)
    • C. event.stopImmediatePropagation()
    • D. event.cancelBubble()

    Explanation: `event.stopPropagation()` prevents the event from bubbling further up the DOM tree (stops calling listeners on parent elements). `event.preventDefault()` prevents the default browser action (e.g., link navigation, form submission) but does NOT stop bubbling. `event.stopImmediatePropagation()` stops bubbling AND prevents other listeners on the SAME element from being called. `cancelBubble` is a legacy IE property, not a method.

  15. 15. A developer needs to access and modify the DOM. Which two statements are correct? (Choose 2)

    • A. `document.querySelector('#myId')` returns the first element matching the CSS selector '#myId'(correct)
    • B. `document.getElementById('myId')` returns a NodeList of all matching elements
    • C. `element.classList.add('active')` adds the CSS class 'active' to the element without removing existing classes(correct)
    • D. `element.innerHTML` is always safe to use for inserting user-provided content

    Explanation: `document.querySelector('#myId')` uses CSS selector syntax and returns the FIRST matching element (or null if not found). `document.getElementById('myId')` returns a single element by ID (not a NodeList — that's `querySelectorAll()`). `element.classList.add('active')` adds a class without removing others — this is the modern way to manipulate classes. `element.innerHTML` with user-provided content is a critical XSS (Cross-Site Scripting) vulnerability — always sanitize user input before setting innerHTML.

  16. 16. In LWC, how does a child component communicate with its parent component?

    • A. By directly modifying a property on the parent component
    • B. By dispatching a CustomEvent that the parent listens for using an event handler(correct)
    • C. By calling a public method (@api) on the parent component
    • D. By updating a shared global variable

    Explanation: In Lightning Web Components, child-to-parent communication follows the event pattern: the child dispatches a CustomEvent using `this.dispatchEvent(new CustomEvent('eventname', { detail: data }))`, and the parent component listens for the event using the `oneventname` attribute on the child component tag or `addEventListener`. This preserves component encapsulation. Direct parent property modification violates LWC's one-way data binding. @api methods on children can be called by parents (parent-to-child), not the reverse.

  17. 17. What does a JavaScript Promise represent?

    • A. A guaranteed synchronous result of an asynchronous operation
    • B. An object representing the eventual completion (or failure) of an asynchronous operation and its resulting value(correct)
    • C. A contract between two JavaScript functions to exchange data
    • D. A memory-safe way to store large data sets asynchronously

    Explanation: A Promise is an object that represents a value that may not be available yet but will be resolved in the future. A Promise is in one of three states: pending (initial state), fulfilled (resolved with a value), or rejected (failed with a reason). Promises are consumed using `.then()` (success handler), `.catch()` (error handler), and `.finally()` (runs regardless of outcome). They replaced callback patterns for managing asynchronous code.

  18. 18. What is the output order of the following code? ```javascript console.log('A'); setTimeout(() => console.log('B'), 0); Promise.resolve().then(() => console.log('C')); console.log('D'); ```

    • A. A, B, C, D
    • B. A, D, C, B(correct)
    • C. A, D, B, C
    • D. A, C, D, B

    Explanation: JavaScript's event loop prioritizes: (1) Synchronous code runs first (A, then D); (2) Microtasks (Promise callbacks) run before macrotasks (C); (3) Macrotasks (setTimeout callbacks, even with 0ms delay) run last (B). So the order is A → D → C → B. This demonstrates the event loop's task queue priority: synchronous → microtask queue (Promises) → macrotask queue (setTimeout/setInterval).

  19. 19. How does `async/await` relate to Promises?

    • A. `async/await` is a separate asynchronous mechanism that does not use Promises
    • B. `async/await` is syntactic sugar over Promises — `await` pauses execution until a Promise resolves and returns the resolved value(correct)
    • C. `await` can only be used with `setTimeout`, not Promises
    • D. An `async` function always runs synchronously if there are no `await` expressions

    Explanation: `async/await` is syntactic sugar over Promises. An `async` function always returns a Promise. `await` can only be used inside an `async` function and pauses that function's execution until the awaited Promise resolves (or rejects), then returns the resolved value (or throws the rejection error). This allows writing asynchronous code in a synchronous-looking style. Under the hood, it's still Promise chaining.

  20. 20. Which two methods on the Promise object allow running multiple promises concurrently? (Choose 2)

    • A. Promise.all() — waits for ALL promises to resolve; rejects immediately if any one rejects(correct)
    • B. Promise.allSettled() — waits for ALL promises to complete (resolve or reject) and returns an array of outcomes(correct)
    • C. Promise.chain() — chains promises together sequentially
    • D. Promise.queue() — queues promises for sequential execution

    Explanation: `Promise.all([p1, p2, p3])` runs all promises concurrently and resolves when ALL resolve (returns array of values), but rejects immediately with the first rejection. `Promise.allSettled([p1, p2, p3])` also runs concurrently but waits for ALL to settle (resolve or reject) and returns an array of `{status, value/reason}` objects — useful when you want all results regardless of failures. `Promise.chain()` and `Promise.queue()` do not exist in the JavaScript standard.

  21. 21. In LWC, which decorator and Apex method call pattern is used to make an asynchronous call to a Salesforce Apex method?

    • A. @wire(apexMethod) with a property decorated with @wire, or an imperative call using apexMethod().then().catch()(correct)
    • B. ajax.callApex() method available in all LWC components
    • C. import { callApex } from 'salesforce/apex' and use synchronously
    • D. Only @wire can call Apex; imperative Apex calls are not supported in LWC

    Explanation: In LWC, there are two patterns for calling Apex: (1) @wire decorator — the result is automatically refreshed when reactive properties change, ideal for data that should always be in sync with the UI; (2) Imperative calls — import the Apex method and call it imperatively like a Promise: `apexMethodName({ params }).then(result => {...}).catch(error => {...})`. Imperative calls are used when you need to trigger the call on user action or control the timing. Both patterns are supported and commonly used.

  22. 22. What is the purpose of the `@api` decorator in a Lightning Web Component?

    • A. To make a property or method private within the component
    • B. To expose a property or method as part of the component's public API, allowing parent components to set the property or call the method(correct)
    • C. To connect the property to Salesforce data using the wire service
    • D. To mark a property as reactive — changes trigger re-render

    Explanation: The `@api` decorator in LWC exposes a property or method as part of the component's public interface. Parent components (or Experience Builder, Lightning App Builder) can set @api properties from outside the component. @api methods can be called by parent components using a template reference (querySelector). Without @api, properties and methods are private to the component. All @api properties are also reactive (changes cause re-render).

  23. 23. Which two lifecycle hooks in LWC are commonly used to perform initialization logic and clean up event listeners? (Choose 2)

    • A. connectedCallback() — called when the component is inserted into the DOM(correct)
    • B. disconnectedCallback() — called when the component is removed from the DOM, used to clean up subscriptions and event listeners(correct)
    • C. constructor() — called when the component is created, used for all initialization including DOM queries
    • D. renderedCallback() — called after every render, ideal for one-time initialization

    Explanation: `connectedCallback()` fires when the component is connected to the DOM — used for initialization like subscribing to message channels, adding event listeners, or fetching data. `disconnectedCallback()` fires when the component is removed from the DOM — used to clean up: unsubscribe from channels, remove event listeners, clear timers. The `constructor()` should only call `super()` and not access DOM elements. `renderedCallback()` is for post-render DOM manipulation but runs after EVERY render — one-time initialization logic needs an `isInitialized` guard.

  24. 24. In an LWC HTML template, how do you conditionally render a section of markup only when a property `isVisible` is true?

    • A. `<div ng-if='isVisible'>...</div>`
    • B. `<template lwc:if={isVisible}>...</template>`(correct)
    • C. `<div if:true={isVisible}>...</div>`
    • D. `<template v-if='isVisible'>...</template>`

    Explanation: In modern LWC (API version 55+), the recommended conditional rendering directive is `lwc:if={condition}`, `lwc:elseif={condition}`, and `lwc:else` on `<template>` elements. The older syntax `if:true={condition}` also works in older API versions but `lwc:if` is the current standard. `ng-if` is Angular syntax; `v-if` is Vue.js syntax. LWC uses its own `lwc:` namespace for structural directives.

  25. 25. A developer wants to query for a specific DOM element inside an LWC component's shadow DOM. Which approach is correct?

    • A. document.querySelector('#myElement')
    • B. this.template.querySelector('#myElement')(correct)
    • C. window.querySelector('#myElement')
    • D. this.querySelector('#myElement')

    Explanation: In LWC, each component's DOM is encapsulated in a Shadow DOM. To query elements inside the component's own shadow root, use `this.template.querySelector('#myElement')` — `this.template` is the reference to the component's shadow root. Using `document.querySelector()` searches the global document DOM and cannot pierce LWC's shadow boundary (Shadow DOM encapsulation prevents this). `this.querySelector()` is not a valid LWC pattern.