Checking that a role sits in a list of permissions, that a word appears in a title, that an extension belongs to the accepted formats: the question of presence comes up everywhere, and it deserves a one-line answer.
includes hands back a boolean, nothing else. That is what makes it readable where indexOf() forced a comparison against a number.
Definition
includes exists both on Array and on String. On an array, it looks for a value among the items. On a string, it looks for a run of characters anywhere in the text.
const roles = ["ROLE_USER", "ROLE_ADMIN"];
console.log(roles.includes("ROLE_ADMIN")); // true
console.log(roles.includes("ROLE_MENTOR")); // false
const sentence = "The JavaScript glossary by Believemy";
console.log(sentence.includes("JavaScript")); // true
console.log(sentence.includes("javascript")); // false, case mattersAn optional second argument gives the position to search from: roles.includes("ROLE_USER", 1) hands back false, since the search starts after that item.
Case, and how to ignore it
The comparison is exact, capitals included. For a case-insensitive search, put both sides in the same shape before comparing.
const title = "JavaScript course";
const query = "javascript";
console.log(title.includes(query)); // false
console.log(title.toLowerCase().includes(query.toLowerCase())); // trueOn text typed by a visitor, add String.trim() before the comparison. One space brought along by a copy and paste is enough to make an otherwise correct search fail, and nobody sees it on screen.
What it finds, and what it misses
The comparison follows the rules of Strict equality (===), with one useful exception: unlike ===, includes recognizes NaN.
console.log([NaN].includes(NaN)); // true
console.log([NaN].indexOf(NaN)); // -1
const users = [{ id: 7 }];
console.log(users.includes({ id: 7 })); // false
console.log(users.some((u) => u.id === 7)); // trueTwo objects written the same way remain two different objects, each with its own address in memory: that is the Reference vs value distinction. To look for an object on a criterion, Array.some() or Array.find() are the right methods.
Frequently asked questions
includes or indexOf()?
includes when only presence matters, indexOf() when the position is needed. The first one avoids the comparison against -1, a reliable source of inverted logic. The second stays useful for cutting a string at a landmark.
Is it expensive on a large list?
The array is walked item by item, so the cost grows with its size. Across a few hundred values, the question does not arise. Across tens of thousands, and inside a loop above all, load the values into a Set: its has method answers without walking anything.
How do you check several values at once?
By turning the question around with Array.some(): formats.some((f) => fileName.endsWith(f)) tests a list of extensions against a single name. The same form checks that a user holds at least one role out of several.