Skip to main content
Module

x/rambda/source/equals.js

Faster and smaller alternative to Ramda
Go to Latest
File
import {type} from './type'import {_isArray} from './_internals/_isArray'
export function _lastIndexOf(valueToFind, list) { if (!_isArray(list)) { throw new Error(`Cannot read property 'indexOf' of ${list}`) } const typeOfValue = type(valueToFind) if (!['Object', 'Array', 'NaN', 'RegExp'].includes(typeOfValue)) return list.lastIndexOf(valueToFind)
const {length} = list let index = length let foundIndex = -1
while (--index > -1 && foundIndex === -1) { if (equals(list[index], valueToFind)) { foundIndex = index } }
return foundIndex}
export function _indexOf(valueToFind, list) { if (!_isArray(list)) { throw new Error(`Cannot read property 'indexOf' of ${list}`) } const typeOfValue = type(valueToFind) if (!['Object', 'Array', 'NaN', 'RegExp'].includes(typeOfValue)) return list.indexOf(valueToFind)
let index = -1 let foundIndex = -1 const {length} = list
while (++index < length && foundIndex === -1) { if (equals(list[index], valueToFind)) { foundIndex = index } }
return foundIndex}
function _arrayFromIterator(iter) { const list = [] let next while (!(next = iter.next()).done) { list.push(next.value) } return list}
function _equalsSets(a, b) { if (a.size !== b.size) { return false } const aList = _arrayFromIterator(a.values()) const bList = _arrayFromIterator(b.values())
const filtered = aList.filter( aInstance => _indexOf(aInstance, bList) === -1 ) return filtered.length === 0}
function parseError(maybeError) { const typeofError = maybeError.__proto__.toString() if (!['Error', 'TypeError'].includes(typeofError)) return []
return [typeofError, maybeError.message]}
function parseDate(maybeDate) { if (!maybeDate.toDateString) return [false]
return [true, maybeDate.getTime()]}
function parseRegex(maybeRegex) { if (maybeRegex.constructor !== RegExp) return [false]
return [true, maybeRegex.toString()]}
function equalsSets(a, b) { if (a.size !== b.size) { return false } const aList = _arrayFromIterator(a.values()) const bList = _arrayFromIterator(b.values())
const filtered = aList.filter( aInstance => _indexOf(aInstance, bList) === -1 ) return filtered.length === 0}
export function equals(a, b) { if (arguments.length === 1) return _b => equals(a, _b)
const aType = type(a)
if (aType !== type(b)) return false if (aType === 'Function') { return a.name === undefined ? false : a.name === b.name }
if (['NaN', 'Undefined', 'Null'].includes(aType)) return true
if (aType === 'Number') { if (Object.is(-0, a) !== Object.is(-0, b)) return false
return a.toString() === b.toString() }
if (['String', 'Boolean'].includes(aType)) { return a.toString() === b.toString() }
if (aType === 'Array') { const aClone = Array.from(a) const bClone = Array.from(b)
if (aClone.toString() !== bClone.toString()) { return false }
let loopArrayFlag = true aClone.forEach((aCloneInstance, aCloneIndex) => { if (loopArrayFlag) { if ( aCloneInstance !== bClone[aCloneIndex] && !equals(aCloneInstance, bClone[aCloneIndex]) ) { loopArrayFlag = false } } })
return loopArrayFlag }
const aRegex = parseRegex(a) const bRegex = parseRegex(b)
if (aRegex[0]) { return bRegex[0] ? aRegex[1] === bRegex[1] : false } else if (bRegex[0]) return false
const aDate = parseDate(a) const bDate = parseDate(b)
if (aDate[0]) { return bDate[0] ? aDate[1] === bDate[1] : false } else if (bDate[0]) return false
const aError = parseError(a) const bError = parseError(b)
if (aError[0]) { return bError[0] ? aError[0] === bError[0] && aError[1] === bError[1] : false } if (aType === 'Set') { return _equalsSets(a, b) } if (aType === 'Object') { const aKeys = Object.keys(a)
if (aKeys.length !== Object.keys(b).length) { return false }
let loopObjectFlag = true aKeys.forEach(aKeyInstance => { if (loopObjectFlag) { const aValue = a[aKeyInstance] const bValue = b[aKeyInstance]
if (aValue !== bValue && !equals(aValue, bValue)) { loopObjectFlag = false } } })
return loopObjectFlag }
return false}