/** * Collection utilities - ES Module Version */ import { typeOf, isObject, isArray, isString, isFunction } from './Type.js'; /** * Iterate over collections */ export function forEach(collection, iterator, that) { const type = typeOf(collection); let i, key; if (type === 'object') { for (key in collection) { if (collection.hasOwnProperty(key)) { if (iterator.call(that, collection[key], key, collection) === false) { break; } } } } else if (type === 'array' || type === 'string') { for (i = 0; i < collection.length; i++) { if (iterator.call(that, collection[i], i, collection) === false) { break; } } } return collection; } /** * Get length of collection */ export function len(collection) { const type = typeOf(collection); if (type === 'array' || type === 'string') { return collection.length; } if (type === 'object') { return Object.keys(collection).length; } return 0; } /** * Extend objects (similar to Object.assign but deeper) */ export function extend(...args) { let target = args[0] || {}; let deep = false; let i = 1; // Check if deep copy if (typeof target === 'boolean') { deep = target; target = args[1] || {}; i = 2; } for (; i < args.length; i++) { const source = args[i]; if (!source) continue; for (const key in source) { if (source.hasOwnProperty(key)) { const src = target[key]; const copy = source[key]; // Prevent infinite loop if (target === copy) continue; if (deep && copy && (isObject(copy) || isArray(copy))) { let clone; if (isArray(copy)) { clone = src && isArray(src) ? src : []; } else { clone = src && isObject(src) ? src : {}; } target[key] = extend(deep, clone, copy); } else if (copy !== undefined) { target[key] = copy; } } } } return target; } /** * Map over collections */ export function map(collection, iterator, that) { const type = typeOf(collection); const result = []; forEach(collection, function(value, key) { result.push(iterator.call(that, value, key, collection)); }); return type === 'string' ? result.join('') : result; } /** * Filter collections */ export function filter(collection, iterator, that) { const type = typeOf(collection); const result = type === 'object' ? {} : []; forEach(collection, function(value, key) { if (iterator.call(that, value, key, collection)) { if (type === 'object') { result[key] = value; } else { result.push(value); } } }); return type === 'string' ? result.join('') : result; } /** * Find in collection */ export function find(collection, iterator, that) { let result; forEach(collection, function(value, key) { if (iterator.call(that, value, key, collection)) { result = value; return false; // break } }); return result; } /** * Check if every element passes test */ export function every(collection, iterator, that) { let result = true; forEach(collection, function(value, key) { if (!iterator.call(that, value, key, collection)) { result = false; return false; // break } }); return result; } /** * Check if any element passes test */ export function some(collection, iterator, that) { let result = false; forEach(collection, function(value, key) { if (iterator.call(that, value, key, collection)) { result = true; return false; // break } }); return result; } /** * Get keys of object or indices of array */ export function keys(collection) { if (isObject(collection)) { return Object.keys(collection); } if (isArray(collection) || isString(collection)) { return Array.from({ length: collection.length }, (_, i) => i); } return []; } /** * Get values of collection */ export function values(collection) { if (isObject(collection)) { return Object.values(collection); } if (isArray(collection)) { return [...collection]; } if (isString(collection)) { return collection.split(''); } return []; } // Export all functions export default { forEach, len, extend, map, filter, find, every, some, keys, values };