JavaScript Array every(): Testing All Elements
Master the JavaScript Array every() method for testing if all elements pass a condition. Learn syntax, use cases, and best practices with practical examples.
The every() method tests whether all elements in an array pass the test implemented by the provided function. It returns a Boolean value - true if all elements pass the test, false otherwise. This method is essential for validation, checking preconditions, and ensuring data integrity.
Understanding every()
The every() method executes a provided function once for each element in the array until it finds one where the function returns a falsy value. If such an element is found, every() immediately returns false. Otherwise, if the function returns a truthy value for all elements, every() returns true.
Basic Syntax and Usage
// Syntax
array.every(callback(element, index, array), thisArg)
// Basic examples
const numbers = [2, 4, 6, 8, 10];
const allEven = numbers.every(num => num % 2 === 0);
console.log(allEven); // true
const mixed = [2, 4, 5, 8, 10];
const allEvenMixed = mixed.every(num => num % 2 === 0);
console.log(allEvenMixed); // false (5 is odd)
// Testing with objects
const users = [
{ name: 'Alice', age: 25, active: true },
{ name: 'Bob', age: 30, active: true },
{ name: 'Charlie', age: 35, active: true }
];
const allActive = users.every(user => user.active);
console.log(allActive); // true
const allAdults = users.every(user => user.age >= 18);
console.log(allAdults); // true
// Empty array returns true
console.log([].every(x => x > 0)); // true (vacuous truth)
// Using all callback parameters
const items = ['apple', 'banana', 'cherry'];
const result = items.every((item, index, array) => {
console.log(`Testing ${item} at index ${index}`);
return item.length > 3 && index < array.length;
});
console.log(result); // true
Early Termination
// every() stops at first false
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let checksPerformed = 0;
const allLessThan5 = numbers.every(num => {
checksPerformed++;
console.log(`Checking ${num}`);
return num < 5;
});
console.log(allLessThan5); // false
console.log(`Checks performed: ${checksPerformed}`); // 5 (stopped at 5)
// Comparison with filter().length
const array = Array.from({ length: 1000000 }, (_, i) => i);
console.time('every');
const everyResult = array.every(n => n < 500000);
console.timeEnd('every'); // Fast - stops early
console.time('filter');
const filterResult = array.filter(n => n < 500000).length === array.length;
console.timeEnd('filter'); // Slow - processes entire array
Common Use Cases
Data Validation
// Form validation
class FormValidator {
constructor(rules) {
this.rules = rules;
}
validate(data) {
const results = {};
// Check if all fields are valid
const isValid = Object.keys(this.rules).every(field => {
const fieldRules = this.rules[field];
const value = data[field];
// Check all rules for this field
const fieldValid = fieldRules.every(rule => {
if (rule.required && !value) {
results[field] = rule.message || 'Field is required';
return false;
}
if (rule.pattern && value && !rule.pattern.test(value)) {
results[field] = rule.message || 'Invalid format';
return false;
}
if (rule.min !== undefined && value < rule.min) {
results[field] = rule.message || `Must be at least ${rule.min}`;
return false;
}
if (rule.custom && !rule.custom(value, data)) {
results[field] = rule.message || 'Validation failed';
return false;
}
return true;
});
return fieldValid;
});
return { isValid, errors: results };
}
}
// Usage
const validator = new FormValidator({
username: [
{ required: true, message: 'Username is required' },
{ pattern: /^[a-zA-Z0-9_]+$/, message: 'Invalid username format' },
{ custom: val => val.length >= 3, message: 'Username too short' }
],
email: [
{ required: true },
{ pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: 'Invalid email' }
],
age: [
{ required: true },
{ min: 18, message: 'Must be 18 or older' }
]
});
const formData = {
username: 'john_doe',
email: 'john@example.com',
age: 25
};
console.log(validator.validate(formData));
// { isValid: true, errors: {} }
Type Checking
// Array type validation
function isArrayOf(array, type) {
if (!Array.isArray(array)) return false;
if (typeof type === 'string') {
return array.every(item => typeof item === type);
}
if (typeof type === 'function') {
return array.every(item => item instanceof type);
}
return false;
}
console.log(isArrayOf([1, 2, 3], 'number')); // true
console.log(isArrayOf(['a', 'b', 'c'], 'string')); // true
console.log(isArrayOf([1, '2', 3], 'number')); // false
// Complex type checking
function validateSchema(data, schema) {
return Object.keys(schema).every(key => {
const value = data[key];
const expectedType = schema[key];
if (expectedType === 'array') {
return Array.isArray(value);
}
if (typeof expectedType === 'object' && expectedType.type) {
// Nested validation
if (expectedType.type === 'array') {
return Array.isArray(value) &&
value.every(item => typeof item === expectedType.items);
}
if (expectedType.type === 'object') {
return typeof value === 'object' &&
validateSchema(value, expectedType.properties);
}
}
return typeof value === expectedType;
});
}
const userSchema = {
id: 'number',
name: 'string',
tags: { type: 'array', items: 'string' },
settings: {
type: 'object',
properties: {
theme: 'string',
notifications: 'boolean'
}
}
};
const userData = {
id: 123,
name: 'John',
tags: ['developer', 'javascript'],
settings: {
theme: 'dark',
notifications: true
}
};
console.log(validateSchema(userData, userSchema)); // true
Permissions and Access Control
// Permission checking
class PermissionChecker {
constructor(userPermissions) {
this.userPermissions = new Set(userPermissions);
}
hasAll(requiredPermissions) {
return requiredPermissions.every(permission =>
this.userPermissions.has(permission)
);
}
hasAny(permissions) {
return permissions.some(permission =>
this.userPermissions.has(permission)
);
}
canAccess(resource) {
if (!resource.requiredPermissions) return true;
if (resource.requireAll) {
return this.hasAll(resource.requiredPermissions);
}
return this.hasAny(resource.requiredPermissions);
}
}
// Role-based access control
class RBAC {
constructor() {
this.roles = new Map();
this.resources = new Map();
}
defineRole(name, permissions) {
this.roles.set(name, permissions);
}
defineResource(name, config) {
this.resources.set(name, config);
}
canUserAccess(userRoles, resourceName) {
const resource = this.resources.get(resourceName);
if (!resource) return false;
// Check if user has all required roles
if (resource.requiredRoles) {
return resource.requiredRoles.every(role =>
userRoles.includes(role)
);
}
// Check if user has all required permissions through roles
if (resource.requiredPermissions) {
const userPermissions = new Set();
userRoles.forEach(role => {
const permissions = this.roles.get(role) || [];
permissions.forEach(p => userPermissions.add(p));
});
return resource.requiredPermissions.every(permission =>
userPermissions.has(permission)
);
}
return true;
}
}
// Usage
const rbac = new RBAC();
rbac.defineRole('admin', ['read', 'write', 'delete']);
rbac.defineRole('editor', ['read', 'write']);
rbac.defineRole('viewer', ['read']);
rbac.defineResource('sensitive-data', {
requiredPermissions: ['read', 'write'],
requireAll: true
});
console.log(rbac.canUserAccess(['admin'], 'sensitive-data')); // true
console.log(rbac.canUserAccess(['viewer'], 'sensitive-data')); // false
Advanced Patterns
Combining with Other Array Methods
// Chaining with filter and every
const products = [
{ name: 'Laptop', price: 999, inStock: true, category: 'Electronics' },
{ name: 'Phone', price: 699, inStock: true, category: 'Electronics' },
{ name: 'Tablet', price: 399, inStock: false, category: 'Electronics' },
{ name: 'Watch', price: 299, inStock: true, category: 'Accessories' }
];
// Check if all electronics are in stock
const allElectronicsInStock = products
.filter(p => p.category === 'Electronics')
.every(p => p.inStock);
console.log(allElectronicsInStock); // false
// Complex validation pipeline
class DataValidator {
constructor() {
this.validators = [];
}
addValidator(name, fn) {
this.validators.push({ name, fn });
return this;
}
validate(data) {
const errors = [];
const isValid = this.validators.every(({ name, fn }) => {
try {
const result = fn(data);
if (!result) {
errors.push(`Validation failed: ${name}`);
}
return result;
} catch (error) {
errors.push(`Validation error in ${name}: ${error.message}`);
return false;
}
});
return { isValid, errors };
}
validateAll(dataArray) {
return dataArray.every(data => this.validate(data).isValid);
}
}
// Usage
const validator = new DataValidator()
.addValidator('hasRequiredFields', data =>
['id', 'name', 'email'].every(field => field in data)
)
.addValidator('validEmail', data =>
/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data.email)
)
.addValidator('positiveId', data =>
data.id > 0
);
const users = [
{ id: 1, name: 'John', email: 'john@example.com' },
{ id: 2, name: 'Jane', email: 'jane@example.com' }
];
console.log(validator.validateAll(users)); // true
Custom every() Implementations
// Async every
async function everyAsync(array, predicate) {
for (let i = 0; i < array.length; i++) {
const result = await predicate(array[i], i, array);
if (!result) return false;
}
return true;
}
// Parallel async every (careful with side effects)
async function everyAsyncParallel(array, predicate) {
const results = await Promise.all(
array.map((item, index) => predicate(item, index, array))
);
return results.every(Boolean);
}
// Usage
async function checkUrls(urls) {
return everyAsync(urls, async (url) => {
try {
const response = await fetch(url);
return response.ok;
} catch {
return false;
}
});
}
// every with timeout
function everyWithTimeout(array, predicate, timeout) {
const startTime = Date.now();
for (let i = 0; i < array.length; i++) {
if (Date.now() - startTime > timeout) {
throw new Error('Timeout exceeded');
}
if (!predicate(array[i], i, array)) {
return false;
}
}
return true;
}
// every with early exit callback
function everyWithExit(array, predicate, onEarlyExit) {
for (let i = 0; i < array.length; i++) {
if (!predicate(array[i], i, array)) {
if (onEarlyExit) {
onEarlyExit(array[i], i);
}
return false;
}
}
return true;
}
// Usage
const numbers = [2, 4, 6, 7, 8];
everyWithExit(
numbers,
n => n % 2 === 0,
(value, index) => console.log(`Failed at index ${index}, value: ${value}`)
);
Nested Structure Validation
// Deep every for nested structures
function deepEvery(obj, predicate, path = '') {
if (Array.isArray(obj)) {
return obj.every((item, index) =>
deepEvery(item, predicate, `${path}[${index}]`)
);
}
if (obj && typeof obj === 'object') {
return Object.keys(obj).every(key =>
deepEvery(obj[key], predicate, path ? `${path}.${key}` : key)
);
}
return predicate(obj, path);
}
// Tree validation
class TreeValidator {
static isValidBinaryTree(node) {
if (!node) return true;
const childrenCount = [node.left, node.right].filter(Boolean).length;
return childrenCount <= 2 &&
this.isValidBinaryTree(node.left) &&
this.isValidBinaryTree(node.right);
}
static isBalanced(node) {
if (!node) return true;
const getHeight = (n) => {
if (!n) return 0;
return 1 + Math.max(getHeight(n.left), getHeight(n.right));
};
const leftHeight = getHeight(node.left);
const rightHeight = getHeight(node.right);
return Math.abs(leftHeight - rightHeight) <= 1 &&
this.isBalanced(node.left) &&
this.isBalanced(node.right);
}
static everyNode(node, predicate) {
if (!node) return true;
return predicate(node) &&
this.everyNode(node.left, predicate) &&
this.everyNode(node.right, predicate);
}
}
// Graph validation
class GraphValidator {
static isFullyConnected(adjacencyList) {
const nodes = Object.keys(adjacencyList);
return nodes.every(node => {
const visited = new Set();
const queue = [node];
while (queue.length > 0) {
const current = queue.shift();
visited.add(current);
adjacencyList[current].forEach(neighbor => {
if (!visited.has(neighbor)) {
queue.push(neighbor);
}
});
}
return visited.size === nodes.length;
});
}
static hasNoCycles(adjacencyList) {
const nodes = Object.keys(adjacencyList);
const visited = new Set();
const recursionStack = new Set();
const hasCycle = (node) => {
visited.add(node);
recursionStack.add(node);
const cycleFound = adjacencyList[node].some(neighbor => {
if (!visited.has(neighbor)) {
return hasCycle(neighbor);
}
return recursionStack.has(neighbor);
});
recursionStack.delete(node);
return cycleFound;
};
return !nodes.some(node => !visited.has(node) && hasCycle(node));
}
}
Performance Optimization
Short-Circuit Evaluation
// Optimize by checking cheap conditions first
const expensiveCheck = (item) => {
// Simulate expensive operation
let sum = 0;
for (let i = 0; i < 1000000; i++) {
sum += Math.random();
}
return sum > 500000;
};
const items = Array.from({ length: 100 }, (_, i) => ({
id: i,
active: i % 2 === 0,
value: Math.random() * 100
}));
// Bad: expensive check first
console.time('expensive first');
const result1 = items.every(item =>
expensiveCheck(item) && item.active && item.value > 50
);
console.timeEnd('expensive first');
// Good: cheap checks first
console.time('cheap first');
const result2 = items.every(item =>
item.active && item.value > 50 && expensiveCheck(item)
);
console.timeEnd('cheap first');
// Memoization for repeated checks
function memoizedEvery(array, predicate) {
const cache = new Map();
return array.every((item, index) => {
const key = JSON.stringify(item);
if (cache.has(key)) {
return cache.get(key);
}
const result = predicate(item, index, array);
cache.set(key, result);
return result;
});
}
Batch Validation
// Batch validation for better performance
class BatchValidator {
constructor(batchSize = 1000) {
this.batchSize = batchSize;
}
validateBatch(items, validators) {
const batches = [];
for (let i = 0; i < items.length; i += this.batchSize) {
batches.push(items.slice(i, i + this.batchSize));
}
return batches.every(batch => {
console.log(`Validating batch of ${batch.length} items`);
return batch.every(item =>
validators.every(validator => validator(item))
);
});
}
async validateBatchAsync(items, asyncValidators) {
for (let i = 0; i < items.length; i += this.batchSize) {
const batch = items.slice(i, i + this.batchSize);
const batchValid = await this.validateSingleBatch(batch, asyncValidators);
if (!batchValid) return false;
// Allow event loop to process other tasks
await new Promise(resolve => setTimeout(resolve, 0));
}
return true;
}
async validateSingleBatch(batch, validators) {
const results = await Promise.all(
batch.map(async item => {
for (const validator of validators) {
const valid = await validator(item);
if (!valid) return false;
}
return true;
})
);
return results.every(Boolean);
}
}
Common Patterns and Best Practices
Validation Helpers
// Common validation utilities
const ValidationHelpers = {
// Check if all elements are unique
allUnique(array) {
const seen = new Set();
return array.every(item => {
if (seen.has(item)) return false;
seen.add(item);
return true;
});
},
// Check if array is sorted
isSorted(array, compareFn = (a, b) => a - b) {
return array.every((item, index) =>
index === 0 || compareFn(array[index - 1], item) <= 0
);
},
// Check if all elements match schema
matchesSchema(array, schema) {
return array.every(item => {
return Object.keys(schema).every(key => {
const schemaValue = schema[key];
const itemValue = item[key];
if (typeof schemaValue === 'function') {
return schemaValue(itemValue);
}
if (schemaValue instanceof RegExp) {
return schemaValue.test(itemValue);
}
return itemValue === schemaValue;
});
});
},
// Range validation
allInRange(array, min, max) {
return array.every(value => value >= min && value <= max);
},
// String validation
allMatch(strings, pattern) {
const regex = pattern instanceof RegExp ? pattern : new RegExp(pattern);
return strings.every(str => regex.test(str));
}
};
// Usage examples
console.log(ValidationHelpers.allUnique([1, 2, 3, 4])); // true
console.log(ValidationHelpers.allUnique([1, 2, 3, 2])); // false
console.log(ValidationHelpers.isSorted([1, 3, 5, 7, 9])); // true
console.log(ValidationHelpers.isSorted([1, 3, 2, 7, 9])); // false
const schema = {
type: 'user',
active: true,
age: age => age >= 18
};
const users = [
{ type: 'user', active: true, age: 25 },
{ type: 'user', active: true, age: 30 }
];
console.log(ValidationHelpers.matchesSchema(users, schema)); // true
Error Collection
// Collect all validation errors (not just first)
function validateAll(array, predicate) {
const errors = [];
let allValid = true;
array.forEach((item, index) => {
try {
if (!predicate(item, index, array)) {
allValid = false;
errors.push({
index,
item,
error: 'Validation failed'
});
}
} catch (error) {
allValid = false;
errors.push({
index,
item,
error: error.message
});
}
});
return { allValid, errors };
}
// Multi-criteria validation
class MultiValidator {
constructor() {
this.criteria = [];
}
add(name, predicate, errorMessage) {
this.criteria.push({ name, predicate, errorMessage });
return this;
}
validateItem(item) {
const failed = this.criteria.filter(({ predicate }) => !predicate(item));
return {
valid: failed.length === 0,
errors: failed.map(({ name, errorMessage }) => ({
criterion: name,
message: errorMessage || `Failed ${name} validation`
}))
};
}
validateAll(items) {
const results = items.map((item, index) => ({
index,
item,
...this.validateItem(item)
}));
return {
allValid: results.every(r => r.valid),
results: results.filter(r => !r.valid)
};
}
}
// Usage
const validator = new MultiValidator()
.add('positive', n => n > 0, 'Must be positive')
.add('even', n => n % 2 === 0, 'Must be even')
.add('reasonable', n => n < 1000, 'Too large');
const numbers = [2, 4, -6, 8, 1001];
console.log(validator.validateAll(numbers));
Real-World Examples
API Request Validation
class APIRequestValidator {
constructor() {
this.rules = new Map();
}
defineEndpoint(path, rules) {
this.rules.set(path, rules);
}
validate(request) {
const rules = this.rules.get(request.path);
if (!rules) return { valid: true };
// Check headers
if (rules.headers) {
const headersValid = Object.entries(rules.headers).every(([key, value]) => {
if (typeof value === 'function') {
return value(request.headers[key]);
}
return request.headers[key] === value;
});
if (!headersValid) {
return { valid: false, error: 'Invalid headers' };
}
}
// Check query parameters
if (rules.query) {
const queryValid = Object.entries(rules.query).every(([key, validator]) => {
return validator(request.query[key]);
});
if (!queryValid) {
return { valid: false, error: 'Invalid query parameters' };
}
}
// Check body
if (rules.body && request.body) {
const bodyValid = this.validateBody(request.body, rules.body);
if (!bodyValid) {
return { valid: false, error: 'Invalid request body' };
}
}
return { valid: true };
}
validateBody(body, schema) {
return Object.entries(schema).every(([key, rule]) => {
const value = body[key];
if (rule.required && value === undefined) {
return false;
}
if (value !== undefined) {
if (rule.type && typeof value !== rule.type) {
return false;
}
if (rule.validator && !rule.validator(value)) {
return false;
}
if (rule.enum && !rule.enum.includes(value)) {
return false;
}
}
return true;
});
}
}
// Usage
const validator = new APIRequestValidator();
validator.defineEndpoint('/api/users', {
headers: {
'Content-Type': 'application/json',
'Authorization': token => token && token.startsWith('Bearer ')
},
body: {
name: { required: true, type: 'string' },
email: {
required: true,
type: 'string',
validator: email => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
},
role: {
required: false,
enum: ['admin', 'user', 'guest']
}
}
});
const request = {
path: '/api/users',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer abc123'
},
body: {
name: 'John Doe',
email: 'john@example.com',
role: 'user'
}
};
console.log(validator.validate(request)); // { valid: true }
Test Suite Validator
class TestSuite {
constructor(name) {
this.name = name;
this.tests = [];
this.beforeEach = null;
this.afterEach = null;
}
addTest(name, fn) {
this.tests.push({ name, fn });
}
setBeforeEach(fn) {
this.beforeEach = fn;
}
setAfterEach(fn) {
this.afterEach = fn;
}
async run() {
console.log(`Running test suite: ${this.name}`);
const results = [];
const allPassed = await this.tests.every(async (test) => {
const context = {};
try {
if (this.beforeEach) {
await this.beforeEach(context);
}
await test.fn(context);
if (this.afterEach) {
await this.afterEach(context);
}
results.push({ test: test.name, passed: true });
console.log(`✓ ${test.name}`);
return true;
} catch (error) {
results.push({
test: test.name,
passed: false,
error: error.message
});
console.log(`✗ ${test.name}: ${error.message}`);
return false;
}
});
return { allPassed, results };
}
// Check if all assertions in a test pass
static assert = {
equal(actual, expected, message) {
if (actual !== expected) {
throw new Error(message || `Expected ${expected}, got ${actual}`);
}
},
arrayEqual(actual, expected, message) {
const equal = actual.length === expected.length &&
actual.every((item, index) => item === expected[index]);
if (!equal) {
throw new Error(message || 'Arrays are not equal');
}
},
deepEqual(actual, expected, message) {
const equal = JSON.stringify(actual) === JSON.stringify(expected);
if (!equal) {
throw new Error(message || 'Objects are not deeply equal');
}
},
throws(fn, message) {
try {
fn();
throw new Error(message || 'Expected function to throw');
} catch (error) {
// Expected
}
}
};
}
// Usage
const suite = new TestSuite('Array every() tests');
suite.addTest('returns true for empty array', () => {
const result = [].every(x => x > 0);
TestSuite.assert.equal(result, true);
});
suite.addTest('returns false when condition fails', () => {
const result = [1, 2, 3, 4, 5].every(x => x < 3);
TestSuite.assert.equal(result, false);
});
suite.addTest('stops at first false', () => {
let count = 0;
[1, 2, 3, 4, 5].every(x => {
count++;
return x < 3;
});
TestSuite.assert.equal(count, 3);
});
suite.run().then(({ allPassed }) => {
console.log(`All tests passed: ${allPassed}`);
});
Conclusion
The every() method is a powerful tool for testing whether all elements in an array satisfy a specific condition. Its early termination behavior makes it efficient for validation scenarios, and its boolean return value makes it perfect for conditional logic. Whether you're validating form data, checking permissions, ensuring data integrity, or implementing complex business rules, every() provides a clean and expressive way to test array elements. Combined with other array methods and modern JavaScript features, it enables elegant solutions for a wide range of validation and testing scenarios.