Overview
Checking if a specific value exists in an array or finding its location is a common task in data validation and UI control. This article clarifies the differences between indexOf and lastIndexOf, which retrieve index positions, and includes, which returns a boolean value. We will implement practical search logic using a tag management system as an example.
Specifications (Input/Output)
Search Method Comparison Table
| Method | Purpose | Return Value | If Not Found | Features |
| indexOf(item, [start]) | Find the first position | Number (Index) | -1 | Searches from the start |
| lastIndexOf(item, [start]) | Find the last position | Number (Index) | -1 | Searches from the end |
| includes(item, [start]) | Check existence only | Boolean | false | More intuitive and faster than indexOf |
The input is the element you want to search for, where primitive values are recommended. The output is either an index number or a boolean value. You can specify a search starting position with the second argument, which defaults to the full range if omitted.
Basic Usage
1. Locate Position (indexOf / lastIndexOf)
These methods identify the position of an element within an array.
const userIds = [101, 205, 303, 205, 401];
// Search from the start and find the first position
console.log(userIds.indexOf(205)); // 1
// Search from the end and find the last occurrence
console.log(userIds.lastIndexOf(205)); // 3
// Value that does not exist
console.log(userIds.indexOf(999)); // -1
2. Check Existence (includes)
This method was introduced in ES2016 and is highly efficient for conditional logic in if statements.
const keywords = ['Error', 'Warning', 'Info'];
if (keywords.includes('Error')) {
console.log('Error included');
}
// Returns true or false
Full Code (HTML / JavaScript)
This demonstration shows a tag management function for a blog post interface. We use includes to prevent duplicate tags from being added and indexOf to locate the correct item for removal.
HTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tag Manager Demo</title>
<style>
.tag-container {
font-family: 'Segoe UI', sans-serif;
max-width: 400px;
padding: 20px;
border: 1px solid #ddd;
border-radius: 8px;
background: #fdfdfd;
}
.input-area {
display: flex;
gap: 10px;
margin-bottom: 15px;
}
input[type="text"] {
flex: 1;
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
}
button {
padding: 8px 16px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover { background-color: #0056b3; }
.tag-list {
display: flex;
flex-wrap: wrap;
gap: 8px;
padding: 0;
list-style: none;
}
.tag {
background-color: #e9ecef;
color: #495057;
padding: 5px 10px;
border-radius: 20px;
font-size: 0.9rem;
display: flex;
align-items: center;
gap: 5px;
}
.tag-remove {
cursor: pointer;
color: #999;
font-weight: bold;
}
.tag-remove:hover { color: #dc3545; }
.message {
margin-top: 10px;
font-size: 0.85rem;
min-height: 1.2em;
}
.error { color: #dc3545; }
.success { color: #28a745; }
</style>
</head>
<body>
<div class="tag-container">
<h3>Tag Management System</h3>
<div class="input-area">
<input type="text" id="tag-input" placeholder="Enter new tag...">
<button id="add-btn">Add</button>
</div>
<ul id="current-tags" class="tag-list">
</ul>
<div id="status-msg" class="message"></div>
</div>
<script src="tag_manager.js"></script>
</body>
</html>
JavaScript
/**
* Tag Management Script
* Practice of duplication check (includes) and deletion position identification (indexOf)
*/
// Current tag list
const tags = ['JavaScript', 'HTML', 'CSS'];
// DOM elements
const tagInput = document.getElementById('tag-input');
const addBtn = document.getElementById('add-btn');
const tagListElement = document.getElementById('current-tags');
const statusMsg = document.getElementById('status-msg');
/**
* Function to render the list
*/
const renderTags = () => {
tagListElement.innerHTML = '';
tags.forEach((tag) => {
const li = document.createElement('li');
li.className = 'tag';
li.innerHTML = `
${tag}
<span class="tag-remove" data-tag="${tag}">×</span>
`;
tagListElement.appendChild(li);
});
// Re-assign event listeners to remove buttons
document.querySelectorAll('.tag-remove').forEach(btn => {
btn.addEventListener('click', (e) => removeTag(e.target.dataset.tag));
});
};
/**
* Function to display messages
*/
const showMessage = (text, type) => {
statusMsg.textContent = text;
statusMsg.className = `message ${type}`;
setTimeout(() => {
statusMsg.textContent = '';
statusMsg.className = 'message';
}, 2000);
};
/**
* Function to add a tag
*/
const addTag = () => {
const newTag = tagInput.value.trim();
if (!newTag) return;
// Use includes for duplication check
if (tags.includes(newTag)) {
showMessage(`"${newTag}" is already added.`, 'error');
return;
}
tags.push(newTag);
renderTags();
showMessage(`"${newTag}" added successfully.`, 'success');
tagInput.value = '';
tagInput.focus();
};
/**
* Function to remove a tag
* @param {string} targetTag - Name of the tag to remove
*/
const removeTag = (targetTag) => {
// Use indexOf to find the position in the array
const index = tags.indexOf(targetTag);
if (index !== -1) {
// Remove the element at that position
tags.splice(index, 1);
renderTags();
showMessage(`"${targetTag}" removed successfully.`, 'success');
}
};
// Initialization
renderTags();
addBtn.addEventListener('click', addTag);
Custom Points
Methods like indexOf and includes are strictly case-sensitive. For example, “Js” and “js” are considered different values. To perform a search regardless of case, you should convert strings using toLowerCase() before comparing them. You can also specify a search starting point using the second argument, which is useful when searching for the second occurrence of a specific value.
Important Notes
These methods rely on strict equality (===), which means they cannot be used to search for objects directly. An array like [{id:1}] will return false when using includes({id:1}) because the object reference is different. For object arrays, use findIndex or some. Additionally, includes can detect NaN and return true, whereas indexOf will return -1 as it cannot find it.
Advanced Usage
Removing Duplicates
You can filter out duplicate elements by checking if the first occurrence of an item matches its current index.
const rawData = ['A', 'B', 'A', 'C', 'B'];
const uniqueData = rawData.filter((item, index, array) => {
return array.indexOf(item) === index;
});
console.log(uniqueData); // ["A", "B", "C"]
Summary
The includes method is the most efficient and recommended choice when you simply need to verify if a value exists, especially within conditional logic. Use indexOf when the exact location is required for tasks like item removal or replacement, and lastIndexOf when you need to search from the end or check for duplicates. These methods are fundamental to array manipulation in JavaScript and should be selected based on the specific requirements of your logic.
