JavaScript 实用方法/API (提供源码🥳) — 01

304 阅读17分钟

系列

简介

本篇主要基于 JavaScript 基本数据结构,自定义了JS常用方法 (类型断言或转换, 指定日期格式等),并提供API源码。


Array

API 列表

Api ScopeApi NameApi Description
ArrayisNonEmptyArray是否是 一个非空数组
ArrayisEmptyArray是否是 一个空数组
ArrayisArray是否是 一个数组
ArraytoArray转换成 数组
ArraynewArray转换成 新数组

API 使用

  import js from 'js-simpler'
  
  const arr = [1,2,3]
  const obj = { length: 1 }
  
  js.isNonEmptyArray({}) // false
  js.isNonEmptyArray([]) // false
  js.isNonEmptyArray([1,2,3]) // true
  
  js.isEmptyArray({}) // false
  js.isEmptyArray([]) // true
  js.isEmptyArray([1,2,3]) // false
  
  js.isArray({}) // false
  js.isArray([]) // true
  js.isArray([1,2,3]) // true
  
  js.toArray(arr) // 返回 arr
  js.toArray(obj) // [undefiend]
  
  js.newArray(arr) // [1,2,3] !== arr
  js.newArray(obj) // [undefiend]

API 源码

export const isNonEmptyArray = (arr: unknown): arr is any[] => {
  return isArray(arr) && arr.length > 0
}

export const isEmptyArray = (arr: unknown): arr is any[] => {
  return isArray(arr) && arr.length === 0
}

export const isArray = (arr: unknown): arr is any[] => {
  return Array.isArray(arr)
}

export const toArray = (...rest: unknown[]): any[] => {
  if (isArray(rest[0]) && rest.length === 1) {
    return rest[0]
  }

  try {
    // @ts-ignore
    return Array.from(...rest)
  } catch /* istanbul ignore next */ {
    return []
  }
}

export const newArray = (...rest: unknown[]): any[] => {
  try {
    // @ts-ignore
    return Array.from(...rest)
  } catch /* istanbul ignore next */ {
    return []
  }
}

Boolean

API 列表

Api ScopeApi NameApi Description
BooleanisTrue是否是 true
BooleanisFalse是否是 false
BooleanisBoolean是否是 Boolean 类型

API 使用

  import js from 'js-simpler'
  
  js.isTrue(1) // false
  js.isTrue(true) // true
  js.isTrue(false) // false
  
  js.isFalse(1) // false
  js.isFalse(true) // false
  js.isFalse(false) // true
  
  js.isBoolean(1) // false
  js.isBoolean(true) // true
  js.isBoolean(false) // true

API 源码

export const isTrue = (bool: unknown): bool is true => {
  return bool === true
}

export const isFalse = (bool: unknown): bool is false => {
  return bool === false
}

export const isBoolean = (bool: unknown): bool is boolean => {
  return bool === true || bool === false
}

Date

API 列表

Api ScopeApi NameApi Description
DateisValidDate是否是 一个合法日期
DateisDate是否是 一个日期 (new Date(NaN))
DatetoDate转换成 日期 Date
DatenewDate转换成 新日期 Date
DateshowDate输出 指定格式的日期文本

API 使用

  import js from 'js-simpler'
  
  const time = 1693455201605 
  const date = new Date(time)
  
  js.isValidDate(new Date(NaN)) // false
  js.isValidDate(date) // true
  js.isValidDate(time) // false
  
  js.isDate(new Date(NaN)) // true
  js.isDate(date) // true
  js.isDate(time) // false
  
  js.toDate(date) // 返回 date
  js.toDate(time) // Date类型, 与date是同个时间, 但 !== date
  js.toDate('2023/8/31 12:13:21.605') // Date类型, 与date是同一个时间点
  js.toDate('2023-8-31 12:13:21.605') // Date类型, 与date是同一个时间点
  
  js.newDate(date) // Date类型, 与date是同个时间, 但 !== date
  js.newDate(time) // Date类型, 与date是同个时间, 但 !== date
  js.newDate('2023/8/31 12:13:21.605') // Date类型, 与date是同一个时间点
  js.newDate('2023-8-31 12:13:21.605') // Date类型, 与date是同一个时间点
  
  js.showDate(time) // 2023-08-31 12:13:21
  js.showDate(date) // 2023-08-31 12:13:21
  js.showDate(time, 'YYYY年MM月DD日 HH:mm:ss.sss') // 2023年08月31日 12:13:21.605
  js.showDate(date, 'YYYY年MM月DD日 HH:mm:ss.sss') // 2023年08月31日 12:13:21.605
  js.showDate('2023/8/31 12:13:21.605', 'YYYY年MM月DD日 HH:mm:ss.sss') // 2023年08月31日 12:13:21.605 
  js.showDate('2023-8-31 12:13:21.605', 'YYYY年MM月DD日 HH:mm:ss.sss') // 2023年08月31日 12:13:21.605

API 源码

import { isNullable } from './~Nullable'
import { isFiniteNumber } from './-Number'
import { isNonEmptyString } from './-String'

export const isValidDate = (date: unknown): date is Date => {
  return isDate(date) && isFiniteNumber(+date)
}

export const isDate = (date: unknown): date is Date => {
  return Object.prototype.toString.call(date) === '[object Date]'
}

export const toDate = (...rest: unknown[]): Date => {
  if (!rest.length) {
    return new Date()
  }

  if (isDate(rest[0])) {
    return rest[0] as Date
  }

  if (isNonEmptyString(rest[0])) {
    let i = 0 as number
    let year = '' as string | number
    let month = '' as string | number
    let date = '' as string | number

    const now = new Date()
    const arr = (rest[0] as string).split(/[/,-]|\s+/)

    for (const [index, number] of arr.entries()) {
      if (index === 0) {
        if (!year && /^\d{4}$/.test(number)) {
          i = index + 1
          year = number
          continue
        }

        if (/^\d{1,2}$/.test(number)) {
          i = index + 1
          month = +number - 1
        }
      }


      if (index === 1) {
        if (!month && month !== 0 && /^\d{1,2}$/.test(number)) {
          i = index + 1
          month = +number - 1
          continue
        }

        if (/^\d{1,2}$/.test(number)) {
          i = index + 1
          date = number
        }
      }

      if (index === 2) {
        if (!date && /^\d{1,2}$/.test(number)) {
          i = index + 1
          date = number
        }
        break
      }
    }

    arr.splice(0, i)

    if (!year) {
      year = now.getFullYear()
    }

    if (!month && month !== 0) {
      month = now.getMonth()
    }

    if (!date) {
      date = now.getDate()
    }

    let hour = '00'
    let minute = '00'
    let seconds = '00'
    let milliseconds = '000'

    const temp = arr.find(time => /^\d{1,2}((:\d{1,2})?(:\d{1,2}([.:]\d{1,3})?)?)?$/.test(time))
    const list = temp?.split(/[:.]/) || []

    for (const [index, number] of list.entries()) {
      if (index === 0) {
        hour = number
      }

      if (index === 1) {
        minute = number
      }

      if (index === 2) {
        seconds = number
      }

      if (index === 3) {
        milliseconds = number
      }
    }

    return new Date(+year, +month, +date, +hour, +minute, +seconds, +milliseconds)
  }

  // @ts-ignore
  return new Date(...rest)
}

export const newDate = (...rest: unknown[]): Date => {
  if (!rest.length) {
    return new Date()
  }

  if (isDate(rest[0])) {
    return new Date(+rest[0]!)
  }

  if (isNonEmptyString(rest[0])) {
    let i = 0 as number
    let year = '' as string | number
    let month = '' as string | number
    let date = '' as string | number

    const now = new Date()
    const arr = (rest[0] as string).split(/[/,-]|\s+/)

    for (const [index, number] of arr.entries()) {
      if (index === 0) {
        if (!year && /^\d{4}$/.test(number)) {
          i = index + 1
          year = number
          continue
        }

        if (/^\d{1,2}$/.test(number)) {
          i = index + 1
          month = +number - 1
        }
      }


      if (index === 1) {
        if (!month && month !== 0 && /^\d{1,2}$/.test(number)) {
          i = index + 1
          month = +number - 1
          continue
        }

        if (/^\d{1,2}$/.test(number)) {
          i = index + 1
          date = number
        }
      }

      if (index === 2) {
        if (!date && /^\d{1,2}$/.test(number)) {
          i = index + 1
          date = number
        }
        break
      }
    }

    arr.splice(0, i)

    if (!year) {
      year = now.getFullYear()
    }

    if (!month && month !== 0) {
      month = now.getMonth()
    }

    if (!date) {
      date = now.getDate()
    }

    let hour = '00'
    let minute = '00'
    let seconds = '00'
    let milliseconds = '000'

    const temp = arr.find(time => /^\d{1,2}((:\d{1,2})?(:\d{1,2}([.:]\d{1,3})?)?)?$/.test(time))
    const list = temp?.split(/[:.]/) || []

    for (const [index, number] of list.entries()) {
      if (index === 0) {
        hour = number
      }

      if (index === 1) {
        minute = number
      }

      if (index === 2) {
        seconds = number
      }

      if (index === 3) {
        milliseconds = number
      }
    }

    return new Date(+year, +month, +date, +hour, +minute, +seconds, +milliseconds)
  }

  // @ts-ignore
  return new Date(...rest)
}

export const showDate = (time: unknown, format?: string): string => {
  const date = !isDate(time)
    ? toDate(time)
    : time

  const template = isNullable(format)
    ? 'YYYY-MM-DD HH:mm:ss'
    : format

  if (isNonEmptyString(template) && isValidDate(date)) {
    return template.replace(/YYYY|MM?|DD?|HH?|mm?|ss?s?|ii?i?/gi, type => {
      switch (type) {
        case 'YYYY': return String(date.getFullYear())
        case 'yyyy': return String(date.getFullYear())
        case 'MM': return String(date.getMonth() >= 9 ? date.getMonth() + 1 : '0' + (date.getMonth() + 1))
        case 'M': return String(date.getMonth() + 1)
        case 'DD': return String(date.getDate() > 9 ? date.getDate() : '0' + date.getMonth())
        case 'dd': return String(date.getDate() > 9 ? date.getDate() : '0' + date.getMonth())
        case 'D': return String(date.getDate())
        case 'd': return String(date.getDate())
        case 'HH': return String(date.getHours() > 9 ? date.getHours() : '0' + date.getHours())
        case 'hh': return String(date.getHours() > 9 ? date.getHours() : '0' + date.getHours())
        case 'H': return String(date.getHours())
        case 'h': return String(date.getHours())
        case 'mm': return String(date.getMinutes() > 9 ? date.getMinutes() : '0' + date.getMinutes())
        case 'm': return String(date.getMinutes())
        case 'ss': return String(date.getSeconds() > 9 ? date.getSeconds() : '0' + date.getSeconds())
        case 's': return String(date.getSeconds())
        case 'sss': return String(date.getMilliseconds() > 99 ? date.getMilliseconds() : date.getMilliseconds() > 9 ? '0' + date.getMilliseconds() : '00' + date.getMilliseconds())
        case 'iii': return String(date.getMilliseconds() > 99 ? date.getMilliseconds() : date.getMilliseconds() > 9 ? '0' + date.getMilliseconds() : '00' + date.getMilliseconds())
        case 'ii': return String(date.getMilliseconds() > 9 ? date.getMilliseconds() : '0' + date.getMilliseconds())
        case 'i': return String(date.getMilliseconds())
      }
      return type
    })
  }

  return ''
}

Error

API 列表

Api ScopeApi NameApi Description
ErrorisError是否是 一个Error
ErrorisURIError是否是 一个URIError
ErrorisTypeError是否是 一个TypeError
ErrorisEvalError是否是 一个EvalError
ErrorisRangeError是否是 一个RangeError
ErrorisSyntaxError是否是 一个SyntaxError
ErrorisReferenceError是否是 一个ReferenceError
ErrornewError实例化 一个Error
ErrornewURIError实例化 一个URIError
ErrornewTypeError实例化 一个TypeError
ErrornewEvalError实例化 一个EvalError
ErrornewRangeError实例化 一个RangeError
ErrornewSyntaxError实例化 一个SyntaxError
ErrornewReferenceError实例化 一个ReferenceError

API 使用

  import js from 'js-simpler'
  
  const urlError = newURIError("url error message") 
  const typeError = newTypeError("type error message")
  
  js.isError(urlError) // true
  js.isError(typeError) // true
  
  js.isURIError(urlError) // true
  js.isURIError(typeError) // false
  
  js.isTypeError(urlError) // false
  js.isTypeError(typeError) // true
  
  // ...

API 源码

export const isError = (err: unknown): err is Error => {
  try { return err instanceof Error } catch /* istanbul ignore next */ { return false }
}

export const isURIError = (err: unknown): err is URIError => {
  try { return err instanceof URIError } catch /* istanbul ignore next */ { return false }
}

export const isTypeError = (err: unknown): err is TypeError => {
  try { return err instanceof TypeError } catch /* istanbul ignore next */ { return false }
}

export const isEvalError = (err: unknown): err is EvalError => {
  try { return err instanceof EvalError } catch /* istanbul ignore next */ { return false }
}

export const isRangeError = (err: unknown): err is RangeError => {
  try { return err instanceof RangeError } catch /* istanbul ignore next */ { return false }
}

export const isSyntaxError = (err: unknown): err is SyntaxError => {
  try { return err instanceof SyntaxError } catch /* istanbul ignore next */ { return false }
}

export const isReferenceError = (err: unknown): err is ReferenceError => {
  try { return err instanceof ReferenceError } catch /* istanbul ignore next */ { return false }
}


export const newError = (message?: string): Error => {
  return new Error(message)
}

export const newURIError = (message?: string): URIError => {
  return new URIError(message)
}

export const newTypeError = (message?: string):TypeError => {
  return new TypeError(message)
}

export const newEvalError = (message?: string): EvalError => {
  return new EvalError(message)
}

export const newRangeError = (message?: string): RangeError => {
  return new RangeError(message)
}

export const newSyntaxError = (message?: string): SyntaxError => {
  return new SyntaxError(message)
}

export const newReferenceError = (message?: string): ReferenceError => {
  return new ReferenceError(message)
}

Function

API 列表

Api ScopeApi NameApi Description
FunctionisGeneratorFunction是否是 一个生成器函数
FunctionisGeneralFunction是否是 一个普通函数
FunctionisAsyncFunction是否是 一个异步函数
FunctionisFunction是否是 一个函数
FunctiontoFunction转换成 函数

API 使用

  import js from 'js-simpler'
  
  const func1 = function test() {} // 不同函数
  const func2 = function* test() {} // 生成器函数
  const func3 = async function test() {} // 异步函数
  const func4 = "'x', 'y', 'return x + y'"
  
  js.isGeneratorFunction(func1) // false
  js.isGeneratorFunction(func2) // true
  js.isGeneratorFunction(func3) // false
  
  js.isGeneralFunction(func1) // true
  js.isGeneralFunction(func2) // false
  js.isGeneralFunction(func3) // false
  
  js.isAsyncFunction(func1) // false
  js.isAsyncFunction(func2) // false
  js.isAsyncFunction(func3) // true
  
  js.isFunction(func1) // true
  js.isFunction(func2) // true
  js.isFunction(func3) // true
  
  js.toFunction(func1) // === func1
  js.toFunction(func2) // === func2
  js.toFunction(func3) // === func3
  js.toFunction(func4) // function (x, y) { return x + y }

API 源码

export const isGeneratorFunction = (func: unknown): func is Function => {
  return Object.prototype.toString.call(func) === '[object GeneratorFunction]'
}

export const isGeneralFunction = (func: unknown): func is Function => {
  return Object.prototype.toString.call(func) === '[object Function]'
}

export const isAsyncFunction = (func: unknown): func is Function => {
  return Object.prototype.toString.call(func) === '[object AsyncFunction]'
}

export const isFunction = (func: unknown): func is Function => {
  return isAsyncFunction(func) || isGeneralFunction(func) || isGeneratorFunction(func)
}

export const toFunction = (...rest: unknown[]): Function => {
  if (isFunction(rest[0])) {
    return rest[0]
  }

  try {
    // @ts-ignore
    return new Function(...rest)
  } catch /* istanbul ignore next */ {
    return () => {}
  }
}

Map

API 列表

Api ScopeApi NameApi Description
MapisNonEmptyMap是否是 一个非空的Map对象
MapisEmptyMap是否是 一个空的Map对象
MapisMap是否是 一个Map对象
MaptoMap转换成 Map对象
MapnewMap转换成 新的Map对象

API 使用

  import js from 'js-simpler'
  
  const obj = { key: 'value' }
  const map1 = new Map([['key', 'value']])
  const map2 = new Map()
  
  js.isNonEmptyMap(map1) // true
  js.isNonEmptyMap(map2) // false
  js.isNonEmptyMap(obj) // false
  
  js.isEmptyMap(map1) // false
  js.isEmptyMap(map2) // true
  js.isEmptyMap(obj) // false
  
  js.isMap(map1) // true
  js.isMap(map2) // true
  js.isMap(obj) // false
  
  js.toMap(map1) // 返回 map1
  js.toMap(obj) // 相当于 new Map([['key', 'value']])
  
  js.newMap(map1) // 相当于 new Map([['key', 'value']])
  js.newMap(obj) // 相当于 new Map([['key', 'value']])

API 源码

import { isObject } from './-Object'
import { isSet } from './-Set'

export const isNonEmptyMap = (map: unknown): map is Map<unknown, unknown> => {
  return isMap(map) && map.size > 0
}

export const isEmptyMap = (map: unknown): map is Map<unknown, unknown> => {
  return isMap(map) && map.size === 0
}

export const isMap = (map: unknown): map is Map<unknown, unknown> => {
  return Object.prototype.toString.call(map) === '[object Map]'
}

export const toMap = (map?: unknown): Map<unknown, unknown> => {
  if (isObject(map)) {
    return new Map(Object.entries(map))
  }

  if (isMap(map)) {
    return map
  }

  if (isSet(map)) {
    return new Map(Array.from(map.values()).entries())
  }

  try {
    // @ts-ignore
    return new Map(map)
  } catch /* istanbul ignore next */ {
    return new Map()
  }
}

export const newMap = (map?: unknown): Map<unknown, unknown> => {
  if (isObject(map)) {
    return new Map(Object.entries(map))
  }

  if (isMap(map)) {
    return new Map(map.entries())
  }

  if (isSet(map)) {
    return new Map(Array.from(map.values()).entries())
  }

  try {
    // @ts-ignore
    return new Map(map)
  } catch /* istanbul ignore next */ {
    return new Map()
  }
}

Number

API 列表

Api ScopeApi NameApi Description
NumberisNaN是否是 NaN
NumberisNumber是否是 一个数值
NumberisInteger是否是 一个安全的整数值
NumberisDecimal是否是 一个有效的数值, 等同于 isFiniteNumber
NumberisInfinity是否是 一个无穷的数值, 包括 -Infinity
NumberisFiniteNumber是否是 一个有效的数值, 等同于 isDecimal
NumbertoFiniteNumber转换成 有效的数值, 等同于 toDecimal
NumbertoDecimal转换成 有效的数值, 等同于 toFiniteNumber
NumbertoInteger转换成 安全的整数值
NumbertoNumber转换成 整数值, 设置第二个参数可进行四舍五入
NumbertoFixed转换成 String类型的数值, 通常用于四舍五入处理

API 使用

  import js from 'js-simpler'
  
  js.isNumber(NaN) // true
  js.isNumber(123456) // true
  js.isNumber('123456') // false
  
  js.isFiniteNumber(NaN) // false, 别名 isDecimal
  js.isFiniteNumber(123456) // true, 别名 isDecimal
  js.isFiniteNumber('123456') // false, 别名 isDecimal
  
  js.isInteger(Infinity) // false
  js.isInteger(100.01) // false
  js.isInteger(10e5) // true
  
  js.isInfinity(-Infinity) // true
  js.isInfinity(Infinity) // true
  js.isInfinity(NaN) // false
  
  js.toInteger('number') // 0
  js.toInteger('123456') // 123456
  js.toInteger('123456px') // 0
  js.toInteger(12345.678) // 12345
  js.toInteger('1234.567') // 1234
  
  js.toNumber('number') // NaN
  js.toNumber('123456') // 123456
  js.toNumber('123456', 2) // 123456
  js.toNumber(12345.678, 2) // 12345.68
  js.toNumber('1234.567', 2) // 1234.57
  
  js.toFiniteNumber('number') // 0, 别名 toDecimal
  js.toFiniteNumber('123456') // 123456, 别名 toDecimal
  js.toFiniteNumber(12345.678, 2) // 12345.68, 别名 toDecimal
  js.toFiniteNumber('1234.567', 2) // 1234.57, 别名 toDecimal
  
  js.toFixed('number') // ''
  js.toFixed('123456') // '123456'
  js.toFixed('123456', 2) // '123456.00'
  js.toFixed(12345.678, 2) // '12345.68'
  js.toFixed('1234.567', 2) // '1234.57'

API 源码

export const isNaN = (num: unknown): num is number => {
  return Number.isNaN(num)
}

export const isNumber = (num: unknown): num is number => {
  return Object.prototype.toString.call(num) === '[object Number]'
}

export const isInteger = (num: unknown): num is number => {
  return isNumber(num) && Number.isSafeInteger(num)
}

export const isDecimal = (num: unknown): num is number => {
  return isNumber(num) && Number.isFinite(num)
}

export const isInfinity = (num: unknown): num is number => {
  return isNumber(num) && (num === Infinity || num === -Infinity)
}

export const isFiniteNumber = (num: unknown): num is number => {
  return isNumber(num) && Number.isFinite(num)
}

export const toFiniteNumber = (num?: unknown, lie = NaN): number => {
  if (num === Infinity) {
    return Number.MAX_SAFE_INTEGER
  }

  if (num === -Infinity) {
    return -Number.MAX_SAFE_INTEGER
  }

  if (isFiniteNumber(+num!)) {
    return isFiniteNumber(lie) && lie >= 0 ? +toFixed(+num!, lie) : +num!
  }

  return 0
}

export const toDecimal = (num?: unknown, lie = NaN): number => {
  if (num === Infinity) {
    return Number.MAX_SAFE_INTEGER
  }

  if (num === -Infinity) {
    return -Number.MAX_SAFE_INTEGER
  }

  if (isFiniteNumber(+num!)) {
    return isFiniteNumber(lie) && lie >= 0 ? +toFixed(+num!, lie) : +num!
  }

  return 0
}

export const toInteger = (num?: unknown, _?: never): number => {
  if (num === Infinity) {
    return Number.MAX_SAFE_INTEGER
  }

  if (num === -Infinity) {
    return -Number.MAX_SAFE_INTEGER
  }

  try {
    return isFiniteNumber(+num!) && parseInt(String(num)) || 0
  } catch /* istanbul ignore next */ {
    return 0
  }
}

export const toNumber = (num?: unknown, lie = NaN): number => {
  return isFiniteNumber(+num!)
    ? isFiniteNumber(lie) && lie >= 0 ? +toFixed(+num!, lie) : +num!
    : +num!
}

export const toFixed = (num?: unknown, lie = NaN): string => {
  if (num === -Infinity) {
    return '-Infinity'
  }

  if (num === Infinity) {
    return 'Infinity'
  }

  num = isFiniteNumber(num) ? num : +num!
  lie = isFiniteNumber(lie) ? lie : NaN
  lie = lie >= 0 ? lie : NaN

  if (isFiniteNumber(num)) {
    let number = 0
    let string = ''
    let decimal = false

    number = isFiniteNumber(lie) ? Math.round(Math.pow(10, lie) * +num) / Math.pow(10, lie) : +num
    string = String(number)
    decimal = string.indexOf('.') !== -1

    if (decimal && lie > 0) {
      return string.split('.')[0] + '.' + string.split('.')[1].padEnd(lie, '0')
    }

    if (!decimal && lie > 0) {
      return string + '.' + ''.padEnd(lie, '0')
    }

    return string
  }

  return ''
}

Object

API 列表

Api ScopeApi NameApi Description
ObjectisNonEmptyObject是否是 一个非空的纯对象
ObjectisEmptyObject是否是 一个空的纯对象
ObjectisObject是否是 一个纯对象
ObjecttoObject转换成 纯对象
ObjectnewObject转换成 新的纯对象

API 使用

  import js from 'js-simpler'
  
  const arr = []
  const obj1 = {}
  const obj2 = { key: 'value' }
  const map3 = new Map([['key', 'value']])
  
  js.isNonEmptyObject(arr) // false
  js.isNonEmptyObject(obj1) // false
  js.isNonEmptyObject(obj2) // true
  
  js.isEmptyObject(arr) // false
  js.isEmptyObject(obj1) // true
  js.isEmptyObject(obj2) // false  
  
  js.isObject(arr) // false
  js.isObject(obj1) // true
  js.isObject(obj2) // true
  
  js.toObject(obj2) // 返回 obj2
  js.toObject(map3) // 相当于 { key: 'value' }
  
  js.newObject(obj2) // 相当于 { key: 'value' }
  js.newObject(map3) // 相当于 { key: 'value' }

API 源码

import { isArray } from './-Array'
import { isMap } from './-Map'
import { isSet } from './-Set'

export const isNonEmptyObject = (obj: unknown): obj is Record<string, unknown> => {
  return isObject(obj) && Object.keys(obj).length > 0
}

export const isEmptyObject = (obj: unknown): obj is Record<string, unknown> => {
  return isObject(obj) && Object.keys(obj).length === 0
}

export const isObject = (obj: unknown): obj is Record<string, unknown> => {
  return Object.prototype.toString.call(obj) === '[object Object]'
}

export const toObject = (obj?: unknown): Record<string, unknown> => {
  if (isObject(obj)) {
    return obj
  }

  if (isArray(obj)) {
    return Object.fromEntries(obj.entries())
  }

  if (isMap(obj)) {
    return Object.fromEntries(obj.entries())
  }

  if (isSet(obj)) {
    return Object.fromEntries(Array.from(obj.values()).entries())
  }

  return {}
}

export const newObject = (obj?: unknown): Record<string, unknown> => {
  if (isObject(obj)) {
    return { ...obj }
  }

  if (isArray(obj)) {
    return Object.fromEntries(obj.entries())
  }

  if (isMap(obj)) {
    return Object.fromEntries(obj.entries())
  }

  if (isSet(obj)) {
    return Object.fromEntries(Array.from(obj.values()).entries())
  }

  return {}
}

Promise

API 列表

Api ScopeApi NameApi Description
PromiseisPromise是否是 一个Promise对象
PromisetoPromise转换成 Promise对象, 当接受数值参数时, 则是一个延时执行的promise
PromisenewPromise返回 新的promise和resolve、reject控制函数

API 使用

  import js from 'js-simpler'
  
  js.isPromise(new Promise(() => {})) // true
  js.isPromise(Promise.resolve()) // true
  js.isPromise(null) // false
  
  js.toPromise(500) // 返回一个promise, 500ms后resolve
  js.toPromise(-500) // 返回一个promise, 500ms后reject
  js.toPromise(() => {}) // 执行完函数后, 返回一个promise
  js.toPromise([1,2,3,4,5,6]) // 返回一个promise, 这个promise是resolve([1,2,3,4,5,6])
  js.toPromise(Promise.resolve()) // 直接返回参数中的promise

API 源码

import { isFiniteNumber } from './-Number'
import { isFunction } from './-Function'

export const isPromise = (val: unknown): val is Promise<unknown> => {
  return Object.prototype.toString.call(val) === '[object Promise]'
}

export const toPromise = <T = unknown>(wait?: Function | number | unknown): Promise<T> => {
  if (isPromise(wait)) {
    return wait as Promise<T>
  }

  if (isFunction(wait)) {
    return Promise.resolve<T>(wait())
  }

  if (isFiniteNumber(wait)) {
    return new Promise<T>((resolve, reject) => {
      wait >= 0 && setTimeout(resolve, wait)
      wait < 0 && setTimeout(reject, -wait)
    })
  }

  return Promise.resolve<T>(wait as T)
}

export const newPromise = <T = unknown>() => {
  const State = {
    promise: null! as Promise<T>,
    resolve: null! as (value: T | PromiseLike<T>) => void,
    reject: null! as (reason?: any) => void
  }

  State.promise = new Promise<T>((resolve, reject) => {
    State.resolve = resolve
    State.reject = reject
  })

  return State as {
    promise: Promise<T>;
    resolve: (value: T | PromiseLike<T>) => void;
    reject: (reason?: any) => void;
  }
}

RegExp

API 列表

Api ScopeApi NameApi Description
RegExpisRegExp是否是 一个正则表达式
RegExptoRegExp转换成 正则表达式
RegExpnewRegExp转换成 新的正则表达式

API 使用

  import js from 'js-simpler'
  
  js.isRegExp(/\w/) // true
  js.isRegExp(new RegExp('\\w')) // true
  
  js.toRegExp(/\w/) // 返回原参数 /\w/
  js.toRegExp(/\w/, 'gi') // 返回 /\w/gi
  js.toRegExp('\\w', 'gi') // 返回 /\w/gi
  js.toRegExp('\\w', true) // 获得 /\\w/, true 参数会对字符串属于正则特殊字符转义
  js.toRegExp('\\w', true, 'gi') // 获得 /\\w/gi, true 参数会对字符串属于正则特殊字符转义
  js.toRegExp('\\w', 'gi', true) // 获得 /\\w/gi, true 参数会对字符串属于正则特殊字符转义
  
  js.newRegExp(/\w/) // 返回 /\w/, 不等于原参数
  js.newRegExp(/\w/, 'gi') // 返回 /\w/gi
  js.newRegExp('\\w', 'gi') // 返回 /\w/gi
  js.newRegExp('\\w', true) // 获得 /\\w/, true 参数会对字符串属于正则特殊字符转义
  js.newRegExp('\\w', true, 'gi') // 获得 /\\w/gi, true 参数会对字符串属于正则特殊字符转义
  js.newRegExp('\\w', 'gi', true) // 获得 /\\w/gi, true 参数会对字符串属于正则特殊字符转义

API 源码

import { isString } from './-String'
import { isBoolean } from './-Boolean'
import { isFiniteNumber } from './-Number'

export const isRegExp = (reg: unknown): reg is RegExp => {
  return Object.prototype.toString.call(reg) === '[object RegExp]'
}

export const toRegExp = (...rest: unknown[]): RegExp => {
  if (isRegExp(rest[0]) && rest.length === 1) {
    return rest[0]
  }

  const regex = isRegExp(rest[0]) ? rest[0] : isString(rest[0]) || isFiniteNumber(rest[0]) ? RegExp(`${rest[0]}`) : /(?:)/
  const flags = isString(rest[1]) ? rest[1] : isString(rest[2]) ? rest[2] : regex.flags
  const isEscape = isBoolean(rest[1]) ? rest[1] : isBoolean(rest[2]) ? rest[2] : false
  const isRegexp = isRegExp(rest[0])

  return !isRegexp && isEscape
    ? new RegExp(regex.source.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'), flags)
    : new RegExp(regex.source, flags)
}

export const newRegExp = (...rest: unknown[]): RegExp => {
  const regex = isRegExp(rest[0]) ? rest[0] : isString(rest[0]) || isFiniteNumber(rest[0]) ? RegExp(`${rest[0]}`) : /(?:)/
  const flags = isString(rest[1]) ? rest[1] : isString(rest[2]) ? rest[2] : regex.flags
  const isEscape = isBoolean(rest[1]) ? rest[1] : isBoolean(rest[2]) ? rest[2] : false
  const isRegexp = isRegExp(rest[0])

  return !isRegexp && isEscape
    ? new RegExp(regex.source.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'), flags)
    : new RegExp(regex.source, flags)
}

Set

API 列表

Api ScopeApi NameApi Description
SetisNonEmptySet是否是 一个非空的Set对象
SetisEmptySet是否是 一个空的Set对象
SetisSet是否是 一个Set对象
SettoSet转换成 Set对象
SetnewSet转换成 新的Set对象

API 使用

  import js from 'js-simpler'
  
  const arr1 = []
  const arr2 = [1,2,3]
  const set1 = new Set()
  const set2 = new Set([1,2,3])
  
  js.isNonEmptySet(arr1) // false
  js.isNonEmptySet(arr2) // false
  js.isNonEmptySet(set1) // false
  js.isNonEmptySet(set2) // true
  
  js.isEmptySet(arr1) // false
  js.isEmptySet(arr2) // false
  js.isEmptySet(set1) // true
  js.isEmptySet(set2) // false
  
  js.isSet(arr1) // false
  js.isSet(arr2) // false
  js.isSet(set1) // true
  js.isSet(set2) // true
  
  js.toSet(set2) // 返回原参数 set1
  js.toSet(arr2) // 相当于 new Set([1,2,3])
  
  js.newSet(set2) // 相当于 new Set([1,2,3])
  js.newSet(arr2) // 相当于 new Set([1,2,3])

API 源码

import { isObject } from './-Object'
import { isArray } from './-Array'
import { isMap } from './-Map'

export const isNonEmptySet = (set: unknown): set is Set<unknown> => {
  return isSet(set) && set.size > 0
}

export const isEmptySet = (set: unknown): set is Set<unknown> => {
  return isSet(set) && set.size === 0
}

export const isSet = (set: unknown): set is Set<unknown> => {
  return Object.prototype.toString.call(set) === '[object Set]'
}

export const toSet = (set?: unknown): Set<unknown> => {
  if (isSet(set)) {
    return set
  }

  if (isObject(set)) {
    return new Set(Object.entries(set))
  }

  if (isArray(set)) {
    return new Set(set)
  }

  if (isMap(set)) {
    return new Set(set.entries())
  }

  return new Set()
}

export const newSet = (set?: unknown): Set<unknown> => {
  if (isObject(set)) {
    return new Set(Object.entries(set))
  }

  if (isArray(set)) {
    return new Set(set)
  }

  if (isMap(set)) {
    return new Set(set.entries())
  }

  if (isSet(set)) {
    return new Set(set.values())
  }

  return new Set()
}

String

API 列表

Api ScopeApi NameApi Description
StringisNonEmptyString是否是 一个非空的字符串类型, 对于字符串,它会先trim(), 再判断是否非空
StringisEmptyString是否是 一个空的字符串类型, 对于字符串,它会先trim(), 再判断是否空值
StringisString是否是 一个字符串类型

API 使用

  import js from 'js-simpler'
  
  const num1 = 1
  const str1 = ''
  const str2 = ' '
  const str3 = 'text'
  
  js.isNonEmptyString(num1) // false
  js.isNonEmptyString(str1) // false
  js.isNonEmptyString(str2) // false
  js.isNonEmptyString(str3) // true
  
  js.isEmptyString(num1) // false
  js.isEmptyString(str1) // true
  js.isEmptyString(str2) // true
  js.isEmptyString(str3) // false
  
  js.isString(num1) // false
  js.isString(str1) // true
  js.isString(str2) // true
  js.isString(str3) // true

API 源码

export const isNonEmptyString = (str: unknown): str is string => {
  return isString(str) && !!str.trim()
}

export const isEmptyString = (str: unknown): str is string => {
  return isString(str) && !str.trim()
}

export const isString = (str: unknown): str is string => {
  return Object.prototype.toString.call(str) === '[object String]'
}

Symbol

API 列表

Api ScopeApi NameApi Description
SymbolisSymbol是否是 一个Symbol对象
SymboltoSymbol转换成 Symbol对象
SymbolnewSymbol转换成 新的Symbol对象
SymboltoSymbolFor转换成 Symbol.for对象, 由于Symbol.for特性, 等同于 newSymbolFor
SymbolnewSymbolFor转换成 Symbol.for对象, 由于Symbol.for特性, 等同于 toSymbolFor

API 使用

  import js from 'js-simpler'
  
  const string = 'text'
  const symbol1 = Symbol('text')
  const symbol2 = Symbol.for('text')
  
  js.isSymbol(string) // false
  js.isSymbol(symbol1) // true
  js.isSymbol(symbol2) // true
  
  js.toSymbol(string) // 相当于 Symbol('text')
  js.toSymbol(symbol1) // 返回原参数 symbol1
  js.toSymbol(symbol2) // 返回原参数 symbol2
  
  js.newSymbol(string) // 相当于 Symbol('text')
  js.newSymbol(symbol1) // 相当于 Symbol('text')
  js.newSymbol(symbol2) // 相当于 Symbol('text')
  
  js.toSymbolFor(string) // 相当于 Symbol.for('text') 等于 symbol2, 别名 newSymbolFor
  js.toSymbolFor(symbol1) // 相当于 Symbol.for('undefined'), 别名 newSymbolFor
  js.toSymbolFor(symbol2) // 返回原参数 symbol2, 别名 newSymbolFor

API 源码

import { isUndef } from './~Nullable'
import { isString } from './-String'

export const isSymbol = (val: unknown): val is symbol => {
  return Object.prototype.toString.call(val) === '[object Symbol]'
}

export const toSymbol = (val?: unknown): symbol => {
  return !isSymbol(val)
    ? isString(val) ? Symbol(val) : Symbol()
    : val
}

export const newSymbol = (val?: unknown): symbol => {
  return isString(val) ? Symbol(val) : Symbol()
}

export const toSymbolFor = (val?: unknown): symbol => {
  return !isSymbol(val) || isUndef(Symbol.keyFor(val))
    ? Symbol.for(isString(val) ? val : 'undefined')
    : val
}

export const newSymbolFor = (val?: unknown): symbol => {
  return !isSymbol(val) || isUndef(Symbol.keyFor(val))
    ? Symbol.for(isString(val) ? val : 'undefined')
    : val
}

WeakMap

API 列表

Api ScopeApi NameApi Description
WeakMapisWeakMap是否是 一个WeakMap对象
WeakMaptoWeakMap转换成 WeakMap对象
WeakMapnewWeakMap转换成 新的WeakMap对象

API 使用

  import js from 'js-simpler'
  
  const key = { name: 'key' }
  const value = { name: 'value' }
  const map2 = new WeakMap([[key, value]])
  const map1 = new WeakMap()
  
  js.isWeakMap(map1) // true
  js.isWeakMap(map2) // true
  js.isWeakMap(value) // false
  js.isWeakMap(key) // false
  
  js.toWeakMap(map1) // 返回原参数 map1
  js.toWeakMap(map2) // 返回原参数 map2
  js.toWeakMap([[key, value]]) // 相当于 new WeakMap([[key, value]])
  
  js.newWeakMap(map1) // 相当于 new WeakMap()
  js.newWeakMap(map2) // 相当于 new WeakMap([[key, value]])
  js.newWeakMap([[key, value]]) // 相当于 new WeakMap([[key, value]])

API 源码

import { isFunction } from './-Function'
import { isPromise } from './-Promise'
import { isRegExp } from './-RegExp'
import { isObject } from './-Object'
import { isArray } from './-Array'
import { isDate } from './-Date'
import { isMap } from './-Map'
import { isSet } from './-Set'

export const isWeakMap = (map: unknown): map is WeakMap<object, unknown> => {
  return Object.prototype.toString.call(map) === '[object WeakMap]'
}

export const toWeakMap = (map?: unknown): WeakMap<object, unknown> => {
  if (isWeakMap(map)) {
    return map
  }

  if (isArray(map)) {
    return new WeakMap(
      (map as Array<[object, unknown]>).filter(arr => isArray(arr) && arr.length === 2).filter(arr => (
        isFunction(arr[0]) ||
        isPromise(arr[0]) ||
        isRegExp(arr[0]) ||
        isObject(arr[0]) ||
        isArray(arr[0]) ||
        isDate(arr[0]) ||
        isMap(arr[0]) ||
        isSet(arr[0])
      ))
    )
  }

  if (isMap(map)) {
    return new WeakMap(
      Array.from((map as Map<object, unknown>).entries()).filter(arr => (
        isFunction(arr[0]) ||
        isPromise(arr[0]) ||
        isRegExp(arr[0]) ||
        isObject(arr[0]) ||
        isArray(arr[0]) ||
        isDate(arr[0]) ||
        isMap(arr[0]) ||
        isSet(arr[0])
      ))
    )
  }

  return new WeakMap()
}

export const newWeakMap = (map?: unknown): WeakMap<any, unknown> => {
  if (isArray(map)) {
    return new WeakMap(
      (map as Array<[object, unknown]>).filter(arr => isArray(arr) && arr.length === 2).filter(arr => (
        isFunction(arr[0]) ||
        isPromise(arr[0]) ||
        isRegExp(arr[0]) ||
        isObject(arr[0]) ||
        isArray(arr[0]) ||
        isDate(arr[0]) ||
        isMap(arr[0]) ||
        isSet(arr[0])
      ))
    )
  }

  if (isMap(map)) {
    return new WeakMap(
      Array.from((map as Map<object, unknown>).entries()).filter(arr => (
        isFunction(arr[0]) ||
        isPromise(arr[0]) ||
        isRegExp(arr[0]) ||
        isObject(arr[0]) ||
        isArray(arr[0]) ||
        isDate(arr[0]) ||
        isMap(arr[0]) ||
        isSet(arr[0])
      ))
    )
  }

  return new WeakMap()
}

WeakSet

API 列表

Api ScopeApi NameApi Description
WeakSetisWeakSet是否是 一个WeakSet对象
WeakSettoWeakSet转换成 WeakSet对象
WeakSetnewWeakSet转换成 新的WeakSet对象

API 使用

  import js from 'js-simpler'
  
  const arr = [{ name: 'array' }]
  const set2 = new WeakSet(arr)
  const set1 = new WeakSet()
  
  js.isWeakSet(set1) // true
  js.isWeakSet(set2) // true
  js.isWeakSet(arr) // false
  
  js.toWeakSet(set1) // 返回原参数 set1
  js.toWeakSet(set2) // 返回原参数 set2
  js.toWeakSet(arr) // 相当于 new WeakSet(arr)
  
  js.newWeakSet(set1) // 相当于 new WeakSet()
  js.newWeakSet(set2) // 相当于 new WeakSet(arr)
  js.newWeakSet(arr) // 相当于 new WeakSet(arr)

API 源码

import { isFunction } from './-Function'
import { isPromise } from './-Promise'
import { isRegExp } from './-RegExp'
import { isObject } from './-Object'
import { isArray } from './-Array'
import { isDate } from './-Date'
import { isMap } from './-Map'
import { isSet } from './-Set'

export const isWeakSet = (set?: unknown): set is WeakSet<object> => {
  return Object.prototype.toString.call(set) === '[object WeakSet]'
}

export const toWeakSet = (set?: unknown): WeakSet<object> => {
  if (isWeakSet(set)) {
    return set
  }

  if (isObject(set)) {
    return new WeakSet(Object.entries(set))
  }

  if (isArray(set)) {
    return new WeakSet((set as Array<object>).filter(
      item => (
        isFunction(item) ||
        isPromise(item) ||
        isRegExp(item) ||
        isObject(item) ||
        isArray(item) ||
        isDate(item) ||
        isMap(item) ||
        isSet(item)
      )
    ))
  }

  if (isMap(set)) {
    return new WeakSet(set.entries())
  }

  if (isSet(set)) {
    return new WeakSet(Array.from((set as Set<object>).values()).filter(
      item => (
        isFunction(item) ||
        isPromise(item) ||
        isRegExp(item) ||
        isObject(item) ||
        isArray(item) ||
        isDate(item) ||
        isMap(item) ||
        isSet(item)
      )
    ))
  }

  return new WeakSet()
}

export const newWeakSet = (set?: unknown): WeakSet<object> => {
  if (isObject(set)) {
    return new WeakSet(Object.entries(set))
  }

  if (isArray(set)) {
    return new WeakSet((set as Array<object>).filter(
      item => (
        isFunction(item) ||
        isPromise(item) ||
        isRegExp(item) ||
        isObject(item) ||
        isArray(item) ||
        isDate(item) ||
        isMap(item) ||
        isSet(item)
      )
    ))
  }

  if (isMap(set)) {
    return new WeakSet(set.entries())
  }

  if (isSet(set)) {
    return new WeakSet(Array.from((set as Set<object>).values()).filter(
      item => (
        isFunction(item) ||
        isPromise(item) ||
        isRegExp(item) ||
        isObject(item) ||
        isArray(item) ||
        isDate(item) ||
        isMap(item) ||
        isSet(item)
      )
    ))
  }

  return new WeakSet()
}