Free sample · answers included
Free Salesforce JavaScript Developer
Practice Questions
18 free JavaScript Developer practice questions from our bank of 300 reviewed questions, picked across all 7 official exam sections in proportion to their weight. Each one shows the correct answer, why it is right and why the others are wrong, and the official documentation it was checked against.
Last updated
What is the JavaScript Developer exam like?
60+5
Scored + unscored questions
105 min
Time limit
65%
Passing score
$200
Registration (retake $100)
Confirm current details in the official JavaScript Developer exam guide.
Questions by exam section
Heavier sections get more questions, the same way the real exam and our 60-question practice exams are weighted.
Variables, Types, and Collections
23% of the examQuestion 1 · Harder
Ursa Major Solar receives panel quantities as strings, and a developer converts them with a one-linemap()call. Refer to the code below:
What is logged to the console?const quantities = ['10', '10', '10'].map(parseInt); console.log(quantities);- A.
[ 10, 10, 10 ] - B.
[ 10, NaN, 2 ] - C.
[ 10, NaN, NaN ] - D.
[ '10', '10', '10' ]
Show the answer and explanationHide the answer
Correct answer: B.[ 10, NaN, 2 ]map()calls its callback with three arguments (the element, its index, and the array), so each call is reallyparseInt('10', index). Index 0 means the radix is treated as unspecified, giving10; radix 1 is invalid, givingNaN; and radix 2 parses'10'as binary, giving2.[ 10, 10, 10 ]is whatmap(Number)ormap(s => parseInt(s, 10))would produce. The all-string result assumesmap()returns the original values, and[ 10, NaN, NaN ]misses that'10'is a valid binary number.- A.
Question 2 · Harder
Users of a Cumulus Financial app in California report that due dates display one day early. The due date arrives from the API as a date-only string. Refer to the code below:
The code logsconst dueDate = new Date('2025-07-04'); console.log(dueDate.getDate());3for these users. What is the cause?- A.Date-only ISO 8601 strings are parsed as UTC midnight, and
getDate()returns the day in the user's local time zone, which is still July 3 in California. - B.
getDate()returns a zero-based day of the month, so the value 3 represents the fourth day. - C.Date-only strings are parsed in local time, but
getDate()always returns the day in UTC. - D.
getDate()returns the day of the week rather than the day of the month.
Show the answer and explanationHide the answer
Correct answer: A. Date-only ISO 8601 strings are parsed as UTC midnight, andgetDate()returns the day in the user's local time zone, which is still July 3 in California.Under the ECMAScript date time string format, a date-only string such as'2025-07-04'is interpreted as UTC, while a date-time string without an offset is interpreted as local time. UTC midnight on July 4 is 5 PM on July 3 in California, andgetDate()reports the local day, so it returns 3.getDate()is one-based (1-31), so the zero-based explanation is wrong, and it returns the day of the month; the day of the week comes fromgetDay(). The explanation that parsing is local and the getter is UTC reverses the actual behavior. Constructing the date withnew Date(2025, 6, 4)or'2025-07-04T00:00:00'avoids the shift.- A.Date-only ISO 8601 strings are parsed as UTC midnight, and
Question 3 · Harder · Choose 3
A Universal Containers developer serializes a case payload before sending it to an external system. Refer to the code below:
Which three statements about the value ofconst payload = { id: 42, note: undefined, closedAt: null, format() { return 'x'; }, tags: ['vip', undefined], created: new Date(0) }; const json = JSON.stringify(payload);jsonare true? Choose 3 answers.- A.
tagsis serialized as["vip"]. - B.The
noteproperty does not appear in the string. - C.
createdis serialized as the number0. - D.
closedAtis serialized asnull. - E.The
formatproperty does not appear in the string.
Show the answer and explanationHide the answer
Correct answers: B. Thenoteproperty does not appear in the string.; D.closedAtis serialized asnull.; E. Theformatproperty does not appear in the string.JSON.stringify()omits object properties whose values areundefinedor functions, so neithernotenorformatappears in the output.nullis a valid JSON value, soclosedAtis kept asnull. Inside arrays,undefinedis not dropped but converted tonull, sotagsbecomes["vip",null]rather than["vip"].Dateobjects are serialized through theirtoJSON()method, which returns an ISO 8601 string ("1970-01-01T00:00:00.000Z"), not a number.- A.
Question 4 · Medium · Choose 2
A developer at Ursa Major Solar writes code to choose a tax rate, but the script fails before any line runs. Refer to the code below:
Which two changes allow the code to log the correct tax rate? Choose 2 answers.const region = 'EU'; const taxRate; if (region === 'EU') { taxRate = 0.2; } else { taxRate = 0.08; } console.log(taxRate);- A.Replace line 2 with
const taxRate = null;and keep theif...elseassignments. - B.Replace line 2 with
let taxRate;and keep theif...elseassignments. - C.Remove line 2 and declare
const taxRate;inside each branch of theif...elsestatement. - D.Replace lines 2 through 7 with
const taxRate = region === 'EU' ? 0.2 : 0.08; - E.Add
'use strict';as the first line of the script.
Show the answer and explanationHide the answer
Correct answers: B. Replace line 2 withlet taxRate;and keep theif...elseassignments.; D. Replace lines 2 through 7 withconst taxRate = region === 'EU' ? 0.2 : 0.08;Aconstdeclaration must be initialized in the same statement, soconst taxRate;raisesSyntaxError: Missing initializer in const declarationand the script never runs. Declaring withletallows the variable to be created without a value and assigned later in either branch, and a conditional (ternary) expression letsconstbe initialized with the correct value in a single statement. Initializing the constant tonullremoves the syntax error, but the later assignments throwTypeError: Assignment to constant variable. Declaringconst taxRate;inside each branch still lacks an initializer, and even with one the block-scoped variable would not be visible toconsole.log. Strict mode does not change the rule thatconstrequires an initializer.- A.Replace line 2 with
Objects, Functions, and Classes
25% of the examQuestion 5 · Medium · Choose 3
A developer at Universal Containers loads a dashboard with<script type="module" src="dashboard.js"></script>instead of a classic script tag. Which three statements are true about how the browser handles dashboard.js? Choose 3 answers.- A.The script is deferred automatically, so it runs after the HTML document has been parsed even without a
deferattribute. - B.Top-level
thisin dashboard.js refers to thewindowobject. - C.The code runs in strict mode even without a
'use strict'directive. - D.The page works when it is opened directly from the local file system with a
file://URL. - E.A
vardeclared at the top level of dashboard.js is scoped to the module and does not become a property ofwindow.
Show the answer and explanationHide the answer
Correct answers: A. The script is deferred automatically, so it runs after the HTML document has been parsed even without adeferattribute.; C. The code runs in strict mode even without a'use strict'directive.; E. Avardeclared at the top level of dashboard.js is scoped to the module and does not become a property ofwindow.Module scripts are deferred by default, so they execute after the document is parsed, and module code always runs in strict mode. Top-level declarations in a module, includingvar, are scoped to that module rather than attached to the global object, so other scripts cannot read them unless the module exports them or assigns them towindowexplicitly. Top-levelthisin a module is undefined, not window. Browsers apply CORS rules to module scripts, so opening the page from afile://URL fails and a local web server is needed for testing.- A.The script is deferred automatically, so it runs after the HTML document has been parsed even without a
Question 6 · Easier
A Universal Containers integration builds an update payload whose key comes from a variable.
What is logged to the console?const field = 'status'; const value = 'Closed'; const update = { [field]: value, field }; console.log(update);- A.
{ field: 'Closed', status: 'status' } - B.
{ status: 'Closed', field: 'status' } - C.
{ status: 'Closed' } - D.A SyntaxError, because object keys cannot come from variables
Show the answer and explanationHide the answer
Correct answer: B.{ status: 'Closed', field: 'status' }Square brackets in an object literal create a computed property name, so[field]evaluates the variable and uses its value,'status', as the key. The shorthandfieldis equivalent tofield: field, which adds a property namedfieldwhose value is the string'status'. The option withfield: 'Closed'reverses the two features,{ status: 'Closed' }ignores the shorthand property, and both syntaxes have been valid since ES2015, so no SyntaxError is thrown.- A.
Question 7 · Harder
Cumulus Financial requires that an account balance can be changed only through thedepositmethod. A developer uses a private class field and then tests it.
What is the result of running this script?class Wallet { #balance = 0; deposit(amount) { this.#balance += amount; return this.#balance; } } const wallet = new Wallet(); console.log(wallet.deposit(50)); console.log(wallet.#balance);- A.
50is logged, and thenundefinedis logged. - B.
50is logged twice. - C.
50is logged, and then aTypeErroris thrown. - D.A
SyntaxErroris reported, and nothing is logged.
Show the answer and explanationHide the answer
Correct answer: D. ASyntaxErroris reported, and nothing is logged.Referencing a private name such as#balanceoutside the class body that declares it is an early error, so the script fails to parse and a SyntaxError is reported before any line runs. Because parsing fails, even the validdepositcall never executes and nothing is logged. Private fields are not ordinary properties that evaluate toundefinedor expose their value outside the class, and the error is not a runtime TypeError raised after the first log.- A.
Question 8 · Medium · Choose 2
The development lead at AW Computing is reviewing a pull request that converts every function in a legacy library to an arrow function. Which two behaviors of arrow functions should the lead consider before approving the change? Choose 2 answers.- A.Arrow functions are hoisted together with their body, so they can be called before their definition.
- B.Arrow functions cannot be called with
new, so any function used as a constructor must stay a regular function. - C.Arrow functions receive
thisfrom the object that calls them, just like regular methods. - D.Arrow functions do not support default parameter values.
- E.Arrow functions do not have their own
argumentsobject, so code that readsargumentsmust switch to rest parameters.
Show the answer and explanationHide the answer
Correct answers: B. Arrow functions cannot be called withnew, so any function used as a constructor must stay a regular function.; E. Arrow functions do not have their ownargumentsobject, so code that readsargumentsmust switch to rest parameters.Arrow functions cannot be used as constructors, so calling one withnewthrows a TypeError, and they do not have their ownargumentsobject, so rest parameters are the replacement. Arrow functions are expressions assigned to variables, so they are not hoisted with their body the way function declarations are. They takethislexically from the surrounding scope rather than from the caller, which is the opposite of how regular methods behave. Default parameters work the same in arrow functions as in regular functions.Question 9 · Harder
A developer at AW Computing writes a function factory for pricing adjustments:
What is logged to the console?function makeMultiplier(factor) { return function (value) { factor = factor + 1; return value * factor; }; } const scale = makeMultiplier(2); const scaleAgain = makeMultiplier(2); console.log(scale(10), scale(10), scaleAgain(10));- A.
20 20 20 - B.
30 30 30 - C.
30 40 30 - D.
30 40 50
Show the answer and explanationHide the answer
Correct answer: C.30 40 30The parameter factor is a variable in makeMultiplier's scope, and the returned closure can both read and reassign it. Each call to scale increments the same factor, so the first call computes 10 * 3 = 30 and the second computes 10 * 4 = 40. scaleAgain comes from a separate call to makeMultiplier, so it has its own factor starting at 2 and returns 30.20 20 20ignores the increment,30 30 30assumes factor resets on each call, and30 40 50assumes both closures share one factor variable.- A.
Browser and Events
17% of the examQuestion 10 · Harder
Refer to the HTML and code below, which Get Cloudy Consulting uses on an approval screen:<div id="panel"> <button id="approve">Approve</button> </div>
What is logged when the Approve button is clicked?const panel = document.querySelector('#panel'); const btn = document.querySelector('#approve'); panel.addEventListener('click', () => console.log('panel')); btn.addEventListener('click', (event) => { console.log('first'); event.stopImmediatePropagation(); }); btn.addEventListener('click', () => console.log('second'));- A.
first - B.
first,second - C.
first,second,panel - D.
first,panel
Show the answer and explanationHide the answer
Correct answer: A.firststopImmediatePropagation()prevents any remaining listeners from being called, both the other listeners on the same element and those on ancestors, so onlyfirstis logged.first,secondis whatstopPropagation()would produce, because that method lets the remaining listeners on the current element run but blocks ancestors.first,second,panelignores the call entirely.first,panelreverses the behavior by skipping the sibling listener while still bubbling to the ancestor.- A.
Question 11 · Harder
Refer to the HTML and code below from a Northern Trail Outfitters task page:<ul id="tasks"> <li class="item">Call</li> <li class="item">Email</li> </ul>
What is logged to the console?const list = document.querySelector('#tasks'); const live = list.getElementsByClassName('item'); const snapshot = list.querySelectorAll('.item'); const li = document.createElement('li'); li.className = 'item'; list.appendChild(li); console.log(live.length, snapshot.length);- A.
2 2 - B.
3 3 - C.
3 2 - D.
2 3
Show the answer and explanationHide the answer
Correct answer: C.3 2getElementsByClassName()returns a liveHTMLCollectionthat always reflects the current DOM, so the appended item appears in it immediately and it reports 3.querySelectorAll()returns a staticNodeList, a snapshot taken when it was called, so it still reports 2.2 2and3 3treat both collections as the same kind, and2 3reverses which one is live.- A.
Question 12 · Medium · Choose 2
Cumulus Financial's single-page account app switches between tabs without reloading the page. Refer to the code below:
Which two statements about this code are true? Choose 2 answers.function showTab(tab) { renderTab(tab); history.pushState({ tab: tab }, '', `/account/${tab}`); } window.addEventListener('popstate', (event) => { renderTab(event.state ? event.state.tab : 'summary'); });- A.Calling
showTab('billing')changes the address bar to/account/billingwithout the browser loading that URL. - B.Calling
showTab('billing')immediately fires apopstateevent, sorenderTab()runs twice. - C.When the user clicks the browser's Back button, the
popstatelistener runs andevent.stateholds the state of the history entry being returned to, ornullfor an entry created withoutpushState(). - D.
pushState()can set the URL to a different origin, such ashttps://partner.example.com/account. - E.The third argument to
pushState()must be an absolute URL, so the relative path/account/billingthrows an error.
Show the answer and explanationHide the answer
Correct answers: A. CallingshowTab('billing')changes the address bar to/account/billingwithout the browser loading that URL.; C. When the user clicks the browser's Back button, thepopstatelistener runs andevent.stateholds the state of the history entry being returned to, ornullfor an entry created withoutpushState().pushState()adds a history entry and updates the URL, and the browser does not attempt to load that URL, which is why single-page apps use it for client-side routing. CallingpushState()does not triggerpopstate; the event fires when the user navigates the session history, for example with the Back or Forward button, andevent.statecarries a copy of that entry's state object. The new URL must have the same origin as the current page, otherwisepushState()throws an exception. A relative URL is allowed and is resolved against the current URL, so/account/billingworks.- A.Calling
Debugging and Error Handling
7% of the examQuestion 13 · Medium · Choose 2
Universal Containers receives cart data from a partner API as a string. Testing found two failure cases: the partner sometimes sends a truncated payload such as{"cart": {"items": [and sometimes sends{}.
Which two values does thefunction countItems(payload) { try { const data = JSON.parse(payload); return data.cart.items.length; } catch (err) { console.log(err.name); return 0; } }catchblock log for these two failure cases? Choose 2 answers.- A.
SyntaxError - B.
ReferenceError - C.
RangeError - D.
TypeError - E.
JSONError
Show the answer and explanationHide the answer
Correct answers: A.SyntaxError; D.TypeErrorJSON.parse()throws aSyntaxErrorwhen the string is not valid JSON, which is what happens with the truncated payload. With{}, parsing succeeds and returns an empty object, sodata.cartisundefinedand readingitemsfromundefinedthrows aTypeError. AReferenceErroris thrown when code refers to an undeclared identifier, but every identifier in the function is declared. ARangeErrorsignals a numeric value outside its allowed range, which neither payload produces. There is no built-inJSONErrortype; JSON parse failures are reported asSyntaxError.- A.
Asynchronous Programming
13% of the examQuestion 14 · Easier
Northern Trail Outfitters is building a trail dashboard that calls three independent APIs: weather, trail conditions, and permits. Each API call returns a Promise. The dashboard must wait until every request has finished, render each widget whose request succeeded, and show an error message only in the widgets whose request failed. Which method should the developer use to combine the three promises?- A.
Promise.all() - B.
Promise.race() - C.
Promise.allSettled() - D.
Promise.any()
Show the answer and explanationHide the answer
Correct answer: C.Promise.allSettled()Promise.allSettled() waits for every input promise to settle and fulfills with an array of outcome objects, each withstatus: 'fulfilled'and avalueorstatus: 'rejected'and areason, so the dashboard can render successes and failures individually. Promise.all() rejects as soon as one request fails, so the results of the successful requests are not available in its rejection. Promise.race() settles with whichever request settles first, so the other two outcomes are lost. Promise.any() fulfills with only the first successful result and rejects with an AggregateError only when all three fail.- A.
Question 15 · Medium · Choose 3
Northern Trail Outfitters logs the name of each trail when a timer fires. The developer declared the counter withlet, expecting each callback to capture its own value. Refer to the code below:
The code logsconst trails = ['Ridge', 'Lake', 'Pine']; let i = 0; while (i < trails.length) { setTimeout(() => console.log(trails[i]), 100); i++; }undefinedthree times instead ofRidge,Lake, andPine. Which three changes make the code log the three trail names? Choose 3 answers.- A.Change
let i = 0;tovar i = 0;. - B.Replace the
whileloop withfor (const trail of trails) { setTimeout(() => console.log(trail), 100); }. - C.Add
const index = i;as the first statement in the loop body and change the callback to() => console.log(trails[index]). - D.Change the delay from
100toi * 100so that each callback runs at a different time. - E.Replace the
whileloop withtrails.forEach((trail) => setTimeout(() => console.log(trail), 100));.
Show the answer and explanationHide the answer
Correct answers: B. Replace thewhileloop withfor (const trail of trails) { setTimeout(() => console.log(trail), 100); }.; C. Addconst index = i;as the first statement in the loop body and change the callback to() => console.log(trails[index]).; E. Replace thewhileloop withtrails.forEach((trail) => setTimeout(() => console.log(trail), 100));.letcreates a new binding for each iteration only when it is declared in aforloop header; hereiis declared once outside the loop, so all three callbacks close over the same variable, which is 3 by the time the timers fire after the loop has finished, andtrails[3]isundefined. Afor...ofloop with aconstvariable, aconstcopy declared inside the loop body, and the parameter of aforEach()callback each give every callback its own binding that holds the current trail or index. Switching tovarkeeps a single shared, function-scoped variable. Staggering the delays changes only when each callback runs, not which variable it reads, so every callback still reads 3.- A.Change
Server Side JavaScript
8% of the examQuestion 16 · Medium · Choose 2
Ursa Major Solar's inventory service uses anEventEmitterfrom the coreeventsmodule to notify other modules when stock levels change. A new developer asks how the emitter behaves. Which two statements are true? Choose 2 answers.- A.
emit()returns a Promise that resolves after every listener has finished. - B.Adding more than 10 listeners for the same event makes the emitter remove the oldest listeners automatically.
- C.When
emit()is called, the listeners run synchronously in the order in which they were registered. - D.A listener registered with
on()is removed automatically after the event fires once. - E.Emitting an
'error'event when no'error'listener is registered throws the error, and the process exits if nothing catches it.
Show the answer and explanationHide the answer
Correct answers: C. Whenemit()is called, the listeners run synchronously in the order in which they were registered.; E. Emitting an'error'event when no'error'listener is registered throws the error, and the process exits if nothing catches it.The events docs state that anEventEmittercalls all listeners synchronously in registration order, and that emitting'error'without at least one'error'listener throws the error, prints a stack trace and exits the process, which is why services should always register an'error'handler.emit()returns a boolean (trueif the event had listeners,falseotherwise), not a Promise. Exceeding the default of 10 listeners only prints a possible memory-leak warning; no listener is removed. Automatic removal after one call is the behaviour ofonce(), while listeners added withon()stay registered until they are removed.- A.
Question 17 · Harder · Choose 2
A Northern Trail Outfitters app runs fine on developer laptops. In the production container,npm installcompletes without errors, but the app crashes at startup withError: Cannot find module 'dayjs'. Which two situations could explain the failure? Choose 2 answers.- A.
dayjsis listed underdevDependencies, and the container setsNODE_ENV=productionbefore runningnpm install. - B.The developer ran
npm install dayjswithout adding the--saveflag, so npm did not record it in package.json. - C.The developer installed it with
npm install dayjs --no-save, so it exists only in their localnode_modulesfolder. - D.package.json lists
dayjswith the caret range^1.11.10instead of an exact version. - E.The team committed package-lock.json to source control alongside package.json.
Show the answer and explanationHide the answer
Correct answers: A.dayjsis listed underdevDependencies, and the container setsNODE_ENV=productionbefore runningnpm install.; C. The developer installed it withnpm install dayjs --no-save, so it exists only in their localnode_modulesfolder.WhenNODE_ENVis set toproduction, npm does not install modules listed indevDependencies(theomitconfig defaults todev), so a runtime package saved as a dev dependency is missing in production.--no-saveprevents saving todependencies, so the package sits in the developer's localnode_modulesbut never reaches package.json or the container. npm saves installed packages todependenciesby default (thesaveconfig defaults totrue), so leaving out--savedoes not explain the failure. A caret range still installs a matching version, and package-lock.json is intended to be committed so every environment installs the same tree.- A.
Testing
7% of the examQuestion 18 · Easier
Cloud Kicks offers a loyalty program to customers who are 18 or older. A developer wrote the function and unit test below, and the test passes.
Which additional assertion makes the test effective at catching the defect inconst assert = require('node:assert/strict'); function isEligible(age) { return age > 18; } assert.strictEqual(isEligible(30), true); assert.strictEqual(isEligible(12), false);isEligible()?- A.
assert.strictEqual(isEligible(65), true); - B.
assert.strictEqual(isEligible(17), false); - C.
assert.strictEqual(isEligible(18), true); - D.
assert.ok(typeof isEligible(30) === 'boolean');
Show the answer and explanationHide the answer
Correct answer: C.assert.strictEqual(isEligible(18), true);The requirement includes customers who are exactly 18, butage > 18returnsfalsefor 18, so an assertion at the boundary that expectsisEligible(18)to betruefails and exposes the off-by-one defect (the fix isage >= 18). Checking 65 repeats the adult case already covered by 30 and passes with the defective code. Checking 17 is a sensible boundary on the other side, but17 > 18isfalse, so it also passes with the defective code. Checking that the result is a boolean verifies the return type, not the eligibility rule. Effective unit tests exercise the values at and around each boundary of a condition.- A.
Where to go after these 18 questions
Free practice questions for other Salesforce Developer certifications
Ready for a full JavaScript Developer practice exam?
Take a timed 60-question exam drawn from all 300 reviewed questions in the real exam's section mix, then drill the sections you miss.