Manuals & specifications
Find reliable JavaScript answers with MDN, the ECMAScript spec, Baseline, browser compatibility tables, and a simple way to read reference entries.
- 01Choose the right sourceUse MDN to learn how a feature works, the spec for exact rules, and compatibility data to see which browsers support it.
- 02Read a reference entryFind the syntax, the inputs, the return value, the examples, the spec link, and browser support on a reference page.
- 03Predict real behaviorFollow Array.prototype.at from the friendly docs down to the main steps in the spec, and guess its results.
Where to find answers you can trust
JavaScript is too big to remember all of it. Working developers don't try. They know where to find answers they can trust, and they read those answers quickly. When a detail matters, they check it with a tiny program.
Two earlier lessons set this up:
- In A short history of JavaScript, you met ECMAScript. It is the official standard for the JavaScript language. A group called TC39, at Ecma International, writes it. You saw editions such as ES5 and ES2015, and a new edition now comes out every year.
- In Engines, runtimes & hosts, you saw that the language and the host are separate. The host is the program that runs your JavaScript, such as a browser. It adds extras, such as the DOM, the page's elements.
This lesson turns that into a habit. First, ask yourself what kind of question you have:
- "What does this JavaScript code do?" Look in a manual for the language, such as MDN.
- "Does this browser have this feature?" Look at compatibility data: a list of which browsers, and which versions, support a feature.
- "How does the page, or the DOM, work?" Look at the host's own rulebooks, such as the WHATWG HTML and DOM standards.
Start with MDN Web Docs, a free website that explains web features with examples. When you need the exact rule, read the ECMAScript specification at tc39.es/ecma262. When you need to know which browsers support a feature, check the Baseline label (on MDN and web.dev), the browser tables on MDN, or caniuse.com.
You don't know how a setting on your phone works. So you open the phone's manual and find the page for that setting. You follow the short steps and see what happens. MDN does the same job for JavaScript features.
- In real life: A phone feature
- In JavaScript: A JavaScript method you want to use
- In real life: The phone's user manual
- In JavaScript: MDN explains the method with examples
- In real life: A short instruction to try
- In JavaScript: A small code example you can run
This lesson follows one small method all the way through: Array.prototype.at(). A method is a function that belongs to a value. You call it with a dot, like scores.at(-1). The full name Array.prototype.at means "the at method that every array has". It reads one item from a list by its position.
It is a small method, but it lets us practice every kind of looking up:
- negative positions, which count from the end
- positions outside the list
- the exact steps in the spec
- which browsers support it
MDN reference pages
REFERENCE MAPMDN Web Docs is usually the first place to look. Each method has a reference page: one page that describes that method. A good reference page quickly answers four questions:
- How do I call it?
- What do the inputs mean?
- What comes back?
- Can I see an example?
Near the bottom, many reference pages also link to the spec and show a table of browser support.
You don't need to read a reference page from top to bottom each time. Use it like a dictionary. Jump to the part that answers your question. Read the notes around it only if your case is unusual.
const scores = [10, 20, 30];
console.log(scores.at(-1));Line 1 makes a list of three scores. Line 2 asks for the item at position -1. For .at(), -1 means the last item. So it prints 30.
const cart = ["tea", "bread"];
console.log(cart.includes("tea"));
console.log(cart.includes("milk"));Line 1 makes a cart with two items. Lines 2 and 3 use includes() to ask whether the cart has an item. They print true and then false.
The value a method gives back to your code is its return value. It isn't always something to show on the screen. Here it is a Boolean, true or false. An if statement can use it to decide what to do next.
Array.prototype.at(index) Syntax at(index) Parameters index: The position to read. 0 is the first item. Negative values count back from the end. Return value The item at that position, or undefined when the position is outside the array. Description Does not change the array. Turns the index into a whole number before it chooses. Examples [10, 20, 30].at(0) // 10 [10, 20, 30].at(-1) // 30 Specifications ECMAScript language specification: Array.prototype.at Browser compatibility Check the table before you rely on it in older browsers.Start here to see how to write the call. at(index) says the method takes one input, called index.
This practice entry follows MDN's usual layout, in our own words. Its parts come in this order:
- a one-line summary
- Syntax: how to write the call
- Parameters: the inputs
- Return value: what comes back
- Description: more details about how it behaves
- Examples
- Specifications: a link to the spec
- Browser compatibility: which browsers support it
When a method surprises you, read Return value and Description first. They usually explain the surprise.
const scores = [10, 20, 30];
console.log(scores.at(-1));
console.log(scores.join(", "));Line 1 makes the scores. Line 2 reads the last one and prints 30. Line 3 prints the whole list again: 10, 20, 30. join(", ") turns the list into one piece of text, with a comma between the items. The list is the same as before. .at() gives you an item, but it doesn't change the array.
So read one part at a time:
- Syntax shows how to write the call.
- Parameters explain the inputs.
- Return value says what you get back. Read it before you use the result.
- Description and Examples show how the method behaves.
- Specifications and Browser compatibility are for when your question is about exact rules or about which browsers support it.
The ECMAScript specification
STEP THROUGHThe ECMAScript specification, or spec for short, is the official rulebook for the JavaScript language. It covers values, syntax, objects, functions, arrays, promises, modules, and many built-in methods.
An engine is the program that runs your JavaScript, such as V8, SpiderMonkey, or JavaScriptCore. The teams that build engines all follow the spec, so every engine gives the same results. Most beginners don't start with the spec. But when you need the exact behavior, the spec has the final answer.
The spec writes each method as an algorithm: a numbered list of steps that produce a result. Before you read the steps for .at(), learn a few words and marks:
- The receiver is the value before the dot in a method call. In
scores.at(-1), the receiver isscores. The spec calls it the this value. - An array-like object is an object with a
lengthand numbered properties, such as0and1. That is enough for.at()to read it. - Names such as
ToObjectandLengthOfArrayLikeare steps inside the spec. They are not JavaScript functions you can call. - "Let
xbe …" means: work out this value and call itx. ?in front of a step means: if this step fails, stop and throw the error.
Here are the spec's steps for Array.prototype.at(index), shortened a little:
- Let
Obe? ToObject(this value). - Let
lenbe? LengthOfArrayLike(O). - Let
relativeIndexbe? ToIntegerOrInfinity(index). - If
relativeIndex ≥ 0, letkberelativeIndex. - Else, let
kbelen + relativeIndex. - If
k < 0ork ≥ len, returnundefined. - Return
? Get(O, ! ToString(𝔽(k))).
In plain words, line by line:
- Turn the receiver into an object. Call it
O. - Read the length of
O. Call itlen. - Turn
indexinto a whole number. Call itrelativeIndex. - If
relativeIndexis 0 or more, use it as the position. Call the positionk. - If it is negative, add it to the length. For
-1in a list of 3,kis3 + -1, which is2. - If
kis below 0, or is the length or more, returnundefined. - Otherwise, turn
kinto a property name, such as"2", and return the value stored there.
So the method does two jobs. First it turns your index into a position. Then it reads that position, or gives back undefined when the position is outside the list.
? and ! doing there?They are marks in the spec, not characters you type in JavaScript. ? means: if this step fails, stop and throw the error. ! means: this step can never fail. That is all you need for now. Stage 12 of the course covers the spec's marks in detail.
Below is a small, real function that copies those steps. It works on ordinary arrays and on simple array-like objects. It does five things, in order:
- reads the length
- turns the index into a whole number
- picks a position
- checks that the position is inside the list
- reads one value
It is a model for learning. It doesn't copy every conversion rule in the spec.
function simplifiedAt(array, index, onStep = () => {}) { if (array === null || array === undefined) throw new TypeError("Expected a list-like value"); const object = Object(array); const length = Math.min(Math.max(Math.trunc(+object.length) || 0, 0), Number.MAX_SAFE_INTEGER); onStep("length", length); const numberIndex = +index; const relativeIndex = Number.isNaN(numberIndex) ? 0 : Math.trunc(numberIndex); onStep("index", relativeIndex); const k = relativeIndex >= 0 ? relativeIndex : length + relativeIndex; onStep("position", k); if (k < 0 || k >= length) { onStep("out-of-range", undefined); return undefined; } const value = object[String(k)]; onStep("value", value); return value;}A few tools in it may be new:
Math.trunc(x)cuts off the part after the decimal point. So1.7becomes1, not2.Number.isNaN(x)checks whetherxisNaN, the special "not a number" value. Line 7 uses0in that case.- On line 4,
Math.maxandMath.minkeep the length between 0 and the largest whole number JavaScript can store exactly. - The
onStepcalls only report each step to the player below. They don't change the result.
The function follows the same rule as .at(): a negative position counts from the end, and a position outside the list gives undefined.
const scores = [10, 20, 30];
console.log(scores.at(1.7));
console.log(scores.at(NaN));
console.log(scores.at(8));Line 1 makes the list. Line 2 uses 1.7. It is cut to 1, so it prints 20. Line 3 uses NaN, which counts as 0, so it prints 10. Line 4 asks for position 8. That is past the end, so it prints undefined.
.at() turns the index into a whole-number position. A negative index is added to the length, so it counts from the end. Then it reads that position. A position past the end gives undefined.const order = { 0: "tea", 1: "bread", length: 2 };
console.log(Array.prototype.at.call(order, 0));
console.log(Array.prototype.at.call(order, -1));Line 1 makes a plain object. It has two numbered properties, 0 and 1, and a length of 2. Lines 2 and 3 run the real array method on that object. .call(order, 0) runs at with order as the receiver and 0 as the index. They print tea and bread. The method only needs a length and numbered properties. It doesn't need a real array.
const drink = "tea";
console.log(drink.at(0));
console.log(drink.at(-1));Line 1 makes a string. Line 2 reads its first letter, and line 3 reads its last letter. They print t and a. Strings have their own .at() method, because a string has positions and a length too. A reference page tells you which kinds of values a method works on.
Pick an index, guess the result, then follow the main steps.
script
const answer = simplifiedAt(letters, -1);console.log(answer);Two exact rules are worth knowing early:
1.7becomes1. It is cut, not rounded up to2.NaNcounts as0.
You don't need to memorize these. Just remember that the spec is where to find them when a bug depends on them.
Baseline and browser support
LIVE CHECKA feature can be in the spec before every user's browser has it. Browsers add new features over time. So there is a second question: "Where does this work?" Compatibility data answers it. It lists which browsers, and which versions, support a feature. Two places to find it:
- The browser tables on MDN, near the bottom of a reference page. They list browser versions. They also add notes, for example when only part of a feature works.
- caniuse.com, a website for quickly checking support for web features.
Baseline is a simple label for the same question. It looks at the main browsers: Chrome, Edge, Firefox, and Safari, on computers and on phones. It has two levels:
- Newly available: the feature works in the latest version of all those browsers.
- Widely available: the feature has worked in all of them for at least 30 months.
Baseline is a quick guide. It doesn't promise that every old browser works.
The table below lists signals you may see in compatibility data. Read each row from left to right: what you see, what it tells you, and what to check next.
| What you see | What does it tell you? | What should you check next? |
|---|---|---|
| Baseline Newly available | The latest versions of the main browsers support it. | Check whether your users have older versions. |
| Baseline Widely available | The main browsers have supported it for at least 30 months. | Check unusual places, such as browsers inside other apps, or old work computers. |
| A version number | That is the first browser version that supports it. | Check whether your app must work in older versions. |
| Partial support | Some parts work, but not the whole feature. | Read the notes to see which parts are missing. |
| Behind a flag | Someone had to switch it on in the browser's settings. | Don't rely on it. Most visitors won't have it switched on. |
console.log(typeof Array.prototype.at === "function");console.log("toSorted" in Array.prototype);console.log(typeof Object.groupBy === "function");console.log(typeof globalThis.structuredClone === "function");A method from the JavaScript language itself. Most current browsers have it.
Array.prototype.at: checking your browser…. A method from the JavaScript language itself. Most current browsers have it.
Feature detection means checking, in code, whether the browser running your code has a feature. Each of the four lines in the experiment prints true or false. true means this browser has the feature. false means it doesn't. Two tools do the checking:
typeof xgives the type ofxas text. For a method, that text is"function"."name" in xistruewhenxcan reach a property calledname.
Other browsers may give other results. So this check doesn't replace looking at compatibility data for your users.
const cart = [];
console.log("at" in cart);
console.log(Object.hasOwn(cart, "at"));Line 1 makes an empty list called cart. Line 2 prints true. The in operator checks whether cart can reach a property called at. Every array can reach it, because all arrays share the methods stored on Array.prototype.
Line 3 prints false. Object.hasOwn checks only the properties stored on cart itself, and at isn't one of them. To check for a feature, "at" in cart is the useful one. Use Object.hasOwn only when you care where a property is stored.
Feature detection can't help with new syntax, meaning new ways of writing code. An old browser can't even read code it doesn't understand, so your check never gets to run. For example, an old browser can't read optional chaining, ?.. Code that uses it must be rewritten before it reaches that browser.
A build tool can do this rewriting for you. It is a program that turns your code into code that the browsers you choose can run. When you use new syntax, check which browsers your build tool is set up for, and check a support table too.
const readLast = (items) =>
typeof items.at === "function" ? items.at(-1) : items[items.length - 1];
const items = ["tea", "bread"];
const olderList = { 0: "tea", 1: "bread", length: 2 };
console.log(readLast(items));
console.log(readLast(olderList));Lines 1 and 2 make a helper called readLast. It checks whether items.at is a function. The ? : then picks one of two paths:
- If the check is
true, it uses the part after?:items.at(-1). - If the check is
false, it uses the part after:, the fallback. A fallback is a backup way to get the same result. Here it isitems[items.length - 1], the last numbered position.
Line 3 makes a real array. Line 4 makes a list-like object that has no .at(). Lines 5 and 6 both print bread. The array takes the first path, and the object takes the fallback.
.at() is there. A new browser takes the left path. An older browser takes the right path. Both paths give "bread".const prices = [3, 1];
const sortedPrices = prices.toSorted();
console.log(sortedPrices.join(", "));
console.log(prices.join(", "));Line 1 makes a list of prices in the order 3, 1. Line 2 uses toSorted() to make a sorted copy. Line 3 prints the copy: 1, 3. Line 4 prints the original, which is still 3, 1.
This is why the Description part of a reference page matters. It tells you whether a method changes your data or gives you a new value. toSorted() is newer, so check browser support before you use it. For older browsers, you can copy the list and sort the copy instead: [...prices].sort(). The [...prices] part makes the copy.
Reading a reference entry
INTERACTIVENow practice reading the small details on a reference page. A syntax line shows how to write the call. at(index) tells you two things: the method is called at, and it takes one input, called index.
Some methods show more than one syntax line. padStart adds characters to the start of a string until the string is long enough. Its page shows two lines:
padStart(targetLength)padStart(targetLength, padString)
Two lines mean there is a short form and a long form. The second input, padString, is optional: you can leave it out. The page tells you what happens then. For padStart, it adds spaces.
at(index)padStart(targetLength)padStart(targetLength, padString)console.log("7".padStart(3));console.log("7".padStart(3, "0"));console.log([10, 20, 30].at(-1));The Return value part matters as much as the inputs. If .at() finds nothing at the position, it returns undefined. It doesn't throw an error. But a list can also hold undefined as a real item. So getting undefined back doesn't always prove the position was empty.
const colors = ["red", "green", "blue"];
console.log(colors[-1]);
console.log(colors.at(-1));Line 1 makes the list. Line 2 uses square brackets with -1. Square brackets don't count backward. They look for a property named "-1". There isn't one, so it prints undefined. Line 3 uses .at(-1) and prints blue.
const items = ["tea", undefined];
console.log(items.at(1));
console.log(items.at(2));Line 1 puts a real undefined at position 1. Line 2 reads that item. Line 3 reads past the end. Both print undefined. If your app must tell these two cases apart, also compare the position with the list's length.
function describeLastSlot(items) {
const lastIndex = items.length - 1;
if (lastIndex < 0) return "no last position";
return "last value: " + String(items.at(-1));
}
console.log(describeLastSlot(["tea", undefined]));
console.log(describeLastSlot([]));Line 2 works out the last position: the length minus 1. Line 3 handles an empty list first. There, the last position would be -1, which means there is none. Line 4 reads .at(-1) only when a last position exists. It prints last value: undefined, then no last position. Now the two cases look different.
Guess the result from the reference entry, then step through the real call.
script
const result = numbers.at(-1);console.log(result);This is the habit to build:
- Read the syntax, so you write a correct call.
- Read the parameters, so you know what the inputs mean.
- Read the return value before you use the result.
- Read the examples to check your idea.
- If an example still surprises you, open the spec link, or run a tiny test in your console.
Where would you look?
SORTEREach source is reliable for a different kind of question. Sort these everyday questions by the place you would check first.
- I want a friendly explanation and examples of
Array.prototype.at(). - I need the exact steps for an index that is negative and has a fraction, like -1.5.
- Can Safari 15 use
structuredClonewithout a fallback? - What does a method give back when the item you asked for isn't there?
- Two engines give different results. Which one follows the official steps?
- Does a feature work in the current versions of the main browsers?
Pick the best first place to look. Each explanation also says when another source helps next.
const firstReference = {
"how-to-call": "MDN reference page",
"exact-rule": "ECMAScript specification",
"browser-support": "compatibility data",
};
function firstReferenceFor(question) {
return firstReference[question];
}
console.log(firstReferenceFor("how-to-call"));
console.log(firstReferenceFor("exact-rule"));
console.log(firstReferenceFor("browser-support"));Lines 1 to 5 make an object. Each property name is a kind of question. Its value is the best first source for that question. Lines 7 to 9 make a function. Line 8 reads the property whose name matches the question. The last three lines print MDN reference page, ECMAScript specification, and compatibility data, in that order.
Where you’ll use this
You'll use reference pages while you write everyday code, not only for rare questions. Say you want to show the last message in a chat:
function readLastMessage(messages) {
const message = messages.at(-1);
if (message === undefined) return "No messages yet";
return message;
}
console.log(readLastMessage(["Hi", "Are you free?"]));
console.log(readLastMessage([]));Line 1 starts a small function. Line 2 reads the last message. Line 3 returns a note, No messages yet, when there is no message. Lines 6 and 7 try a list with messages and an empty list. They print Are you free? and then No messages yet.
MDN tells you how .at() works. Compatibility data tells you whether older browsers need a fallback.
function lastMessageLabel(messages) {
return messages.at(-1)?.toUpperCase() ?? "No messages yet";
}
console.log(lastMessageLabel(["tea", "bread"]));
console.log(lastMessageLabel([]));Line 2 does the same job in one line. It uses two operators:
?.is called optional chaining. If the value on its left isundefinedornull, it stops and givesundefined. It doesn't calltoUpperCase().??gives the value on its right when the value on its left isundefinedornull. Here, that isNo messages yet.
It prints BREAD and then No messages yet. Use this short form when an empty list is normal. Don't use it to hide a value that should always be there. If such a value is missing, the data has a problem, and your code should treat it as an error. The later Optional chaining & nullish coalescing lesson explains these operators in more detail.
function profileLabel(profile) {
return profile?.name?.toUpperCase() ?? "Guest";
}
console.log(profileLabel({ name: "Asha" }));
console.log(profileLabel(null));Line 1 starts a small function. Line 2 reads the profile's name only if the profile and the name both exist. If not, it gives Guest. It prints ASHA and then Guest.
This check is right when visitors without an account are normal. But think of a checkout page where the user must be signed in. There, a missing profile is a problem. Your code should show an error, not quietly treat the user as a guest.
The table below sums up the parts of a reference page. Read each row from left to right: the part, what it tells you, and a good habit for using it.
| Part of the page | What does it tell you? | What is a good habit? |
|---|---|---|
| Syntax | It shows how to write the call. | Copy the shape of the call, then fill in your own values. |
| Parameters | It explains what each input means. | Check which inputs are optional, and what happens if you leave them out. |
| Return value | It says what the method gives back. | Read it before you call another method on the result. |
| Description | It covers unusual cases, and whether your data changes. | Look for words like changes, returns, copy, or throws. |
| Examples | They show small calls and their results. | Run a tiny version in your console. |
| Specifications | It links to the official, exact rules. | Open it when an unusual case matters. |
| Browser compatibility | It shows which browser versions support the method. | Check it before you use a newer feature. |
Common misconceptions
“Real developers memorize the whole language.”
They remember the big ideas and look up the details. Knowing where to look is a real skill, not a weakness.
“MDN is the specification.”
MDN is a reference written to help people. It links to the spec, but the ECMAScript spec is the official rulebook for the language.
“If the spec has a feature, every browser supports it.”
Browsers take time to add new features. Check compatibility data when some users may have older browsers.
“Baseline means old browsers are guaranteed.”
Baseline describes support in recent versions of the main browsers. You still need to know which browsers your users have.
“The ECMAScript spec covers every web API.”
It covers only the JavaScript language. Browser extras, such as the DOM, are described in other specs, such as the WHATWG HTML and DOM standards.
The spec's steps are not JavaScript code. But they are exact enough that engine builders, test writers, and spec editors can discuss them one step at a time.
Practice: read the reference
6 EXERCISESIn the practice reference entry above, what does .at() return when the position is outside the array?
The Return value part says a position outside the array gives undefined. Your code should be ready for that value.
.at() resultsDon't run it yet. Guess the two lines it prints.
console.log([10, 20, 30].at(-1));
console.log([10, 20, 30].at(5));The first line prints 30, the last item. The second line prints undefined, because position 5 is past the end.
The page for padStart shows two syntax lines: padStart(targetLength) and padStart(targetLength, padString). Which input is optional?
console.log("7".padStart(3));
console.log("7".padStart(3, "0"));padString is optional. If you leave it out, padStart adds spaces. If you pass "0", it adds zeros.
Pick a newer feature, such as Array.prototype.toSorted or Object.groupBy. Where should you look to decide whether older browsers need a fallback?
Use the browser compatibility table on MDN, caniuse.com, or the Baseline label. The answer changes over time as browsers update. So learn the habit of checking, not one version number.
This code reads past the end of the array. What value should it check for before it uses item?
const item = ["first", "second"].at(2);
console.log(item);const item = ["first", "second"].at(2);
if (item === undefined) {
console.log("No item there");
}.at(2) returns undefined here. Check for that before you treat the result as a real string.
A message panel should show the newest message. When there are no messages, it should show a friendly note instead. Add a check before you use the value from .at(-1).
function readLastMessage(messages) {
return messages.at(-1).toUpperCase();
}
console.log(readLastMessage([]));function readLastMessage(messages) {
const message = messages.at(-1);
if (message === undefined) {
return "No messages yet";
}
return message;
}
console.log(readLastMessage(["tea", "bread"]));
console.log(readLastMessage([]));The function checks for undefined before it returns a message. It prints bread for a list with messages and No messages yet for an empty list.
Quiz: check your understanding
7 QUESTIONSYour score counts only your first try at each question. Read every explanation. Together they show which question each source answers: MDN, the spec, or compatibility data.
Question 1 of 7You want friendly examples for a JavaScript method. Where should you usually look first?
Choose an answer to see the explanation.
Question 2 of 7What does this print?
Read the code, then predictconsole.log([10, 20, 30].at(-1));Choose an answer to see the explanation.
Question 3 of 7A syntax line like
padStart(targetLength, padString)has an optional second input. What does optional mean?Choose an answer to see the explanation.
Question 4 of 7What does this call with a fraction print?
Read the code, then predictconsole.log([10, 20, 30].at(1.7));Choose an answer to see the explanation.
Question 5 of 7What does the label Baseline Newly available tell you?
Choose an answer to see the explanation.
Question 6 of 7Which source would you use to answer: can Safari 15 use
structuredClone?Choose an answer to see the explanation.
Question 7 of 7Why does this lesson explain the
?and!marks in spec steps only briefly?Choose an answer to see the explanation.
Key takeaways
- MDN Web Docs is the friendly first place to look. It has reference pages, examples, and practical notes.
- The ECMAScript spec is the official rulebook for the language. Browser extras, such as the DOM, are described in other specs.
- Compatibility data says which browsers support a feature. Baseline Newly available means the latest versions of the main browsers support it. Widely available means they have supported it for at least 30 months.
- Read a reference page one part at a time: syntax, parameters, return value, description, examples, specifications, and browser compatibility.
- When a result matters, check it with a tiny real program or test.
Remember the one-liner.
MDN shows you how to use a feature, the spec says exactly what it does, and compatibility data tells you where it works.
Coming next: Setting up your tools: VS Code, the DevTools console, and Node.js.