equals.js

/**

 * @function equals
 * @description Autocurried function that checks for equality of 2 items
 * @param {*} x - Left side of the equality check
 * @param {*} y - Right side of the equality check
 * @return {boolean}
 * @example
 *
 * const nan = Number.NaN
 * equal(nan, nan) // returns true
 *
 * const arr1 = [0, 1, 2, 3]
 * const arr2 = [null, 1, 2, 3]
 * equals(arr1, arr2) // returns false
 *
 * equals(new Object({'a': 0, 'b': 1}), {'a': 0, 'b': 1}) // true
 *
 */
import curry from './curry'
import exists from './exists'
import identical from './identical'
import type from './type'
import not from './not'
import or from './or'
import isObject from './object/is'
import isArray from './array/is'
import isBoolean from './boolean/is'
import isNumber from './number/is'
import isString from './string/is'
import isDate from './date/is'
import equalsArray from './array/equals'
import equalsObject from './object/equals'

export default curry(function equals (x, y) {
  if (identical(x, y)) return true

  if (type(x) !== type(y)) return false

  if (or(not(exists(x)), not(exists(y)))) return false

  if (x.constructor !== y.constructor) return false

  if (isString(x) || isBoolean(x) || isNumber(x) || isDate(x)) {
    return identical(x.valueOf(), y.valueOf())
  }
  if (isArray(x)) {
    return equalsArray(x, y)
  } else if (isObject(x)) {
    return equalsObject(x, y)
  }
  return false
})