Javascript 高效開發工具庫

前端開發中經常會遇到ArrayObjectStringNumber等數據處理,或者是防抖節流函數等性能優化,抑或 URL 參數處理、類型判斷等等操作,爲了提高開發效率,我將這些常見公共方法進行抽離並封裝好,發佈在 npm 上,後續如有更優的寫法也會做進一步的更新。另外讀者朋友們如果有好的建議或者想爲本項目貢獻一份力的話,歡迎爲本項目提交 pr,一起探討和交流。

安裝

$ npm i --save nutils-js

使用

const nutils = require('nutils-js')
nutils.multArray([1, 2, 3], 2)

目錄

數組

對象

函數

字符串

數字

瀏覽器

由於文章篇幅過長,公衆號上只截取重點部分,如果需要最新完整版,請點擊「閱讀原文」跳到GitHub倉庫進行查看

如果對本文有啥疑問或建議,歡迎加我微信qqlcx55一起學習哈

一、數組

multArray二維數組轉換

將數組(array)拆分成多個子數組,並將這些子數組組成一個新數組。

multArray(array, count)

參數

示例

multArray([1, 2, 3, 4, 5, 6, 7], 2)
=[[1, 2][3, 4][5, 6][7]]

multArray(['a''b''c''d'], 3)
=[['a''b''c']['d']]

源碼

function multArray(arr, count = 8) {
    let pages = []
    arr.forEach((item, index) ={
        const page = Math.floor(index / count)
        if (!pages[page]) pages[page] = []
        pages[page].push(item)
    })
    return pages
}

flatten扁平化數組

將多層嵌套數組(array)拆分成一個數組

flatten(array)

參數

示例

flatten([1, [2][3][4, 5]])

// [1, 2, 3, 4, 5]

源碼

// 扁平化  Map 方法
const flatten = arr =[].concat(...arr.map(v =(Array.isArray(v) ? flatten(v) : v)))

// 扁平化  reduce 方法
const flatten = arr => arr.reduce((a, c) => a.concat(Array.isArray(c) ? flatten(c) : c)[])

flattenDeep指定層級扁平化數組

將多層嵌套數組(array)拆分成指定層級數組

flattenDeep(array, depth)

參數

示例

flattenDeep([1, [2, [3, [4]], 5]], 1)
// =[1, 2, [3, [4]], 5]

// ES6方法 `flat(depth)`
;[1, [2, [3, [4]], 5]].flat(1)
// =[1, 2, [3, [4]], 5]

源碼

const flattenDeep = (arr, depth = 1) => arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v)[])

isArrayEqual檢查兩個數組各項相等

比較兩個數組內的各項值是否相等,返回一個Boolean

isArrayEqual(array, array)

參數

示例

isArrayEqual([6, 5, 2, 4, 1, 3][1, 2, 3, 4, 5, 6])
// =true

isArrayEqual([6, 5, 2, 7, 1, 3][1, 2, 3, 4, 5, 6])
// => false

源碼

const isArrayEqual = (a, b, has = true) ={
    if (a.length !== b.length) return (has = false)
    const s = new Set(b)
    if (a.find(x => !s.has(x))) return (has = false)
    return has
}

allEqual檢查數組各項相等

allEqual(array)

參數

示例

allEqual([1, 2, 3, 4, 5, 6])
// =false

allEqual([1, 1, 1, 1])
// => true

源碼

const allEqual = arr => arr.every(val =val === arr[0])

diffArray具有唯一array值的數組

創建一個具有唯一 array 值的數組,每個值不包含在其他給定的數組中

diffArray(array, array2)

參數

示例

diffArray([1, 2, 6, 7][1, 2, 9, 5])
// =[ 6, 7 ]

源碼

const diffArray = (a, b) ={
    const s = new Set(b)
    let arr = a.filter(x => !s.has(x))
    return arr
}

haveArr具有共同array值的數組

創建一個具有共同 array 值的數組,每個值包含在其他給定的數組中

haveArr(array, array2)

參數

示例

haveArr([1, 2, 6, 7][1, 2, 9, 5])
// =[ 1, 2 ]

源碼

const haveArr = (a, b) ={
    const s = new Set(b)
    return a.filter(x => s.has(x))
}
// ES6 includes
const haveArr = (arr, values) => arr.filter(v => values.includes(v))

uniqueArray數組去重

創建一個去重後的 array 數組副本

uniqueArray(array)

參數

示例

uniqueArray([1, 2, 2, 3, 4, 4, 5])
// =[ 1, 2, 3, 4, 5 ]

源碼

const uniqueArray = (...arr) =[...new Set(arr)]

const uniqueArray = (...arr) => Array.from(new Set(arr))

uniqueArrayObject數組對象去重

創建一個去重後的 array 數組對象副本

uniqueArrayObject(array)

參數

示例

const responseList = [
    { id: 1, a: 1 },
    { id: 2, a: 2 },
    { id: 3, a: 3 },
    { id: 1, a: 4 },
    { id: 2, a: 2 },
    { id: 3, a: 3 },
    { id: 1, a: 4 },
    { id: 2, a: 2 },
    { id: 3, a: 3 },
    { id: 1, a: 4 },
    { id: 2, a: 2 },
    { id: 3, a: 3 },
    { id: 1, a: 4 },
]

uniqueArrayObject(responseList, 'id')

// =[ { id: 1, a: 1 }{ id: 2, a: 2 }{ id: 3, a: 3 } ]

源碼

const uniqueArrayObject = (arr, key) ={
    return arr.reduce((acc, cur) ={
        const ids = acc.map(item => item[key])
        return ids.includes(cur[key]) ? acc : [...acc, cur]
    }[])
}

treeData生成樹結構數據

該函數傳入一個數組, 每項id對應其父級數據parent_id,返回一個樹結構數組

treeData(array, id, parent_id)

參數

示例

const comments = [
    { id: 1, parent_id: null },
    { id: 2, parent_id: 1 },
    { id: 3, parent_id: 1 },
    { id: 4, parent_id: 2 },
    { id: 5, parent_id: 4 },
]

treeData(comments)

// =[ { id: 1, parent_id: null, children: [ [Object][Object] ] } ]

源碼

const treeData = (arr, id = null, link = 'parent_id') => arr.filter(item => item[link] === id).map(item =({ ...item, children: treeData(arr, item.id) }))

ascArr數組升序

返回升序後的新數組

sort() 方法會改變原數組,默認按 unicode 碼順序排列

ascArr(array)

參數

示例

ascArr([3, 2, 3, 4, 1])
// =[ 1, 2, 3, 3, 4 ]

源碼

// 通過ES6 ...展開運算符淺拷貝一份新數組
const ascArr = arr =[...arr].sort((a, b) => a - b)

descArr數組降序

返回降序後的新數組

descArr(array)

參數

示例

descArr([3, 2, 3, 4, 1])
// =[ 1, 2, 3, 3, 4 ]

源碼

const descArr = arr =[...arr].sort((a, b) => b - a)

shuffle隨機排序

創建一個隨機的數組,使用Fisher-Yates算法隨機排序數組的元素

shuffle(array)

參數

示例

shuffle([2, 3, 1])
// =[3, 1, 2]

源碼

const shuffle = ([...arr]) ={
    let m = arr.length
    while (m) {
        const i = Math.floor(Math.random() * m--)
        ;[arr[m], arr[i]] = [arr[i], arr[m]]
    }
    return arr
}

takeArray截取數組開始指定的元素

從 array 數組的最開始一個元素開始提取 n 個元素

takeArray(array, n)

參數

示例

takeArray([2, 3, 1], 2)
// =[2, 3]

源碼

const takeArray = (arr, n = 1) => arr.slice(0, n)

takeLastArray截取數組最後指定的元素

從 array 數組的最後一個元素開始提取 n 個元素

takeLastArray(array, n)

參數

示例

takeArray([2, 3, 1], 2)
// =[3, 1]

源碼

const takeLastArray = (arr, n = 1) => arr.slice(0, -n)

cloneArray克隆數組

淺拷貝一份數組副本

cloneArray(array)

參數

示例

cloneArray([1, 24])
// =[1, 24]

源碼

// ES6 ...
const cloneArray = arr =[...arr]

// ES6 Array.from
const cloneArray = arr => Array.from(arr)

// concat()
const cloneArray = arr =[].concat(arr)

// map()
const cloneArray = arr => arr.map(x => x)

cloneArray([1, 24]) // [1, 24]

maxArray數組中最大值

過濾原數組中所有的非假值元素,返回數組中的最大值

maxArray(array)

參數

示例

maxArray([0, -1, -2, -3, false])
// =0

源碼

const maxArray = arr => Math.max(...arr.filter(v => Boolean(v) || v === 0))

minArray數組中最小值

過濾原數組中所有的非假值元素,返回數組中的最小值

minArray(array)

參數

示例

minArray([0, -1, -2, -3, false])
// => -3

源碼

const minArray = (arr) => Math.min(...arr.filter((v) => Boolean(v) || v === 0));

validArray去除數組中的無效值

創建一個新數組,包含原數組中所有的非假值元素。例如false, null,0, "", undefined, 和 NaN 都是被認爲是 “假值”。

validArray(array)

參數

示例

minArray([0, 1, false, 2, '', 3])
// =[1, 2, 3]

源碼

const validArray = arr => arr.filter(Boolean)

二、對象

isObjectEqual檢查兩個對象各項值相等

isObjectEqual(object, object2)

參數

示例

isObjectEqual({ a: 2, b: 4 }{ b: 4, a: 2 })
// =true
isObjectEqual({ a: 2, b: 4, c: 6 }{ b: 4, a: 2 })
// => false

源碼

function isObjectEqual(obj1, obj2, has = true) {
    // 判斷類型
    const o1 = obj1 instanceof Object
    const o2 = obj2 instanceof Object
    if (!o1 || !o2) return obj1 === obj2
    // 判斷長度
    const keys1 = Object.getOwnPropertyNames(obj1)
    const keys2 = Object.getOwnPropertyNames(obj2)
    if (keys1.length !== keys2.length) return false
    // 各項對比
    for (let o in obj1) {
        let t1 = obj1[o] instanceof Object
        let t2 = obj2[o] instanceof Object
        if (t1 && t2) {
            has = diffByObj(obj1[o], obj2[o])
        } else if (obj1[o] !== obj2[o]) {
            has = false
            break
        }
    }
    return has
}

cloneObject克隆對象

淺拷貝一份對象副本

cloneObject(object)

參數

  1. object要複製的對象

示例

const a = { x: 1, y: 1 }
const b = cloneObject(a)
// => a !== b

源碼

// ES6 ...
const cloneObject = (obj, temp = {}) =(temp = { ...obj })

// Object.assign()
const cloneObject = obj => Object.assign({}, obj)

三、函數

debounce函數防抖

在事件被觸發 n 秒後再執行回調,如果在這 n 秒內又被觸發,則重新計時。

debounce(fn, wait)

參數

示例

debounce(()={ console.log('debounce') }, 1000)
// => 1秒後打印'debounce'

源碼

/** *
 * 防抖
 * @parmas fn 回調函數
 * @parmas time 規定時間
 */
const debounce = (function () {
    let timer = {}
    return function (func, wait = 500) {
        let context = this // 注意 this 指向
        let args = arguments // arguments中存着e
        let name = arguments[0].name || 'arrow' //箭頭函數
        if (timer[name]) clearTimeout(timer[name])
        timer[name] = setTimeout(() ={
            func.apply(this, args)
        }wait)
    }
})()

throttle函數節流

規定一個單位時間,在這個單位時間內,只能有一次觸發事件的回調函數執行,如果在同一個單位時間內某事件被觸發多次,只有一次能生效。

throttle(fn, wait)

參數

示例

throttle(() ={
    console.log('throttle')
}, 1000)
// 1秒多次觸發打印一次`throttle`

源碼

/** *
 * 節流(規定的時間才觸發)
 * @parmas fn 結束完運行的回調
 * @parmas delay 規定時間
 */
export const throttle = (function () {
    let timeout = null
    return function (func, wait) {
        let context = this
        let args = arguments
        if (!timeout) {
            timeout = setTimeout(() ={
                timeout = null
                func.apply(context, args)
            }wait)
        }
    }
})()

throttle(fn, 300)

typeFn類型判斷

判斷是否是 Array Object String Number類型

typeFn.type(value)

參數

示例

typeFn.String('1')
typeFn.Number(1)
typeFn.Boolean(false)
typeFn.Null(null)
typeFn.Array([1, 2])
typeFn.Object({ a: 1 })
typeFn.Function(() ={})

// => true

源碼

let typeFn = {}
const curring = (fn, arr = []) ={
    let len = fn.length
    return (...args) ={
        arr = arr.concat(args)
        if (arr.length < len) {
            return curring(fn, arr)
        }
        return fn(...arr)
    }
}

function isType(type, content) {
    return Object.prototype.toString.call(content) === `[object ${type}]`
}
;['String''Number''Boolean''Null''Array''Object''Function'].forEach(type ={
    typeFn[type] = curring(isType)(type)
})

calcFn加減乘除運算

因爲 JavaScript 遵循 IEEE 754 數學標準,使用 64 位浮點數進行運算。在進行十進制運算時會導致精度丟失。

calcFn.add(value1, value2, value3)

參數

示例

解決 0.1+0.2 !== 0.3 問題
//加法
calcFn.add(0.1, 0.2) // 0.3

//減法
calcFn.sub(0.1, 0.2) // 0.1

//乘法
calcFn.mul(0.2, 0.3) // 0.06

// 乘法
calcFn.add(0.1, 0.2) // 0.5

源碼

const calcFn = {
  add() {
      let arg = Array.from(arguments);
      return arg.reduce((total, num) ={
          return accAdd(total, num);
      });
  },
  sub() {
      let arg = Array.from(arguments);
      return arg.reduce((total, num) ={
          return accAdd(total, -num);
      });
  },
  mul() {
      let arg = Array.from(arguments);
      return arg.reduce((total, num) ={
          return accMul(total, num);
      });
  },
  div() {
      let arg = Array.from(arguments);
      return arg.reduce((total, num) ={
          return accDiv(total, num);
      });
  }
}

function accAdd(arg1, arg2) {
  let r1, r2, m;
  try {
      r1 = arg1.toString().split(".")[1].length;
  } catch (e) {
      r1 = 0;
  }
  try {
      r2 = arg2.toString().split(".")[1].length;
  } catch (e) {
      r2 = 0;
  }
  m = Math.pow(10, Math.max(r1, r2));
  return (arg1 * m + arg2 * m) / m;
}

function accMul(arg1, arg2) {
  let m = 0,
      s1 = arg1.toString(),
      s2 = arg2.toString();
  try {
      m += s1.split(".")[1].length;
  } catch (e) {}
  try {
      m += s2.split(".")[1].length;
  } catch (e) {}
  return Number(s1.replace(".""")) * Number(s2.replace(".""")) / Math.pow(10, m);
}

function accDiv(arg1, arg2) {
  let t1 = 0,
      t2 = 0,
      r1, r2;
  try {
      t1 = arg1.toString().split(".")[1].length;
  } catch (e) {}
  try {
      t2 = arg2.toString().split(".")[1].length;
  } catch (e) {}
  r1 = Number(arg1.toString().replace("."""));
  r2 = Number(arg2.toString().replace("."""));
  return (r1 / r2) * Math.pow(10, t2 - t1);
}

四、字符串

isNil值是否是nullundefined

isNil(value)

參數

示例

isNil(null)
isNil(undefined)
// => true

源碼

const isNil = val =val === undefined || val === null

padStart遮住字符串

padStart(value, n, maskChar)

參數

示例

padStart('18659808664')
// => 1865*******

源碼

const padStart = (str, n = 4, maskChar = '*') => str.slice(0, n).padStart(str.length, maskChar)

thousands數字每隔三位數加分號

thousands(number)

參數

示例

thousands(12255555.2323)
// => 12,255,555.2323

源碼

const thousands = num => num.toString().replace(num.toString().indexOf('.') > -1 ? /(\d)(?=(\d{3})+\.)/g : /(\d)(?=(\d{3})+$)/g, '$1,')

五、數字

randomNumber指定範圍的隨機整數

randomNumber(min, max)

參數

示例

randomNumber(0, 10)
// =7
// =2

源碼

const randomNumber = (min = 0, max = 10) => Math.floor(Math.random() * (max - min + 1)) + min

average求平均值

average(value1, value2, value3)

參數

示例

average(...[1, 2, 3])
average(1, 2, 3)
// =2

源碼

const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length

averageBy檢查數組對象各項相等

averageBy(array, fn)

參數

示例

averageBy([{ n: 4 }{ n: 2 }{ n: 8 }{ n: 6 }]o => o.n)
averageBy([{ n: 4 }{ n: 2 }{ n: 8 }{ n: 6 }]'n')
// =5

源碼

const averageBy = (arr, fn) => arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) / arr.length

aboutEqual兩個值是否約等於

傳入兩個數字是否大致相等,誤差在可接受範圍內

aboutEqual(n1, n2, epsilon)

參數

示例

aboutEqual(1.25, 1.2, 0.06)
// => true

源碼

const aboutEqual = (n1, n2, epsilon = 0.001) => Math.abs(n1 - n2) < epsilon

getLineSize計算兩點之間的距離

勾股定理計算兩點之間的距離

getLineSize = (x1, y1, x2, y2)

參數

示例

getLineSize(0, 0, 3, 4)
// =5

源碼

const getLineSize = (x1, y1, x2, y2) => Math.hypot(x2 - x1, y2 - y1)

sum數組中值總和

sum(value1, value2, value3)

參數

示例

sum(1, 2, 3, 4)
sum(...[1, 2, 3, 4])
// =10

源碼

const sum = (...arr) =[...arr].reduce((acc, val) => acc + val, 0)

六、瀏覽器

copyTextH5 複製文本

copyText(content, callback)

參數

示例

copyText(content, text ={
    this.$toast(text)
})

源碼

function copyText(content, callback) {
    if (!document.queryCommandSupported('copy')) {
        //爲了兼容有些瀏覽器 queryCommandSupported 的判斷
        console.log('瀏覽器不支持')
        return
    }
    let textarea = document.createElement('textarea')
    textarea.value = content
    textarea.readOnly = 'readOnly'
    document.body.appendChild(textarea)
    textarea.select() // 選擇對象
    textarea.setSelectionRange(0, content.length) //核心
    let result = document.execCommand('copy') // 執行瀏覽器複製命令
    callback && callback(result ? '複製成功~~' : '複製失敗~~')
    textarea.remove()
}

getCurrentURL獲取當前的 URL 地址

該函數返回當前頁面的 URL 地址。

示例

getCurrentURL()
// =>

源碼

const getCurrentURL = () => window.location.href

scrollToTop返回頂部

平滑地滾動到當前頁面的頂部。

示例

scrollToTop()
// => 當前頁面的頂部

源碼

const scrollToTop = () ={
    const c = document.documentElement.scrollTop || document.body.scrollTop
    if (c > 0) {
        window.requestAnimationFrame(scrollToTop)
        window.scrollTo(0, c - c / 8)
    }
}

smoothScroll平滑滾動頁面

平滑滾動到瀏覽器窗口的可見區域

示例

smoothScroll('#fooBar');
// => 平滑滾動到ID爲fooBar的元素
smoothScroll ('.fooBar' );
// => 使用fooBar類平滑滾動到第一個元素

源碼

const smoothScroll = element =>
    document.querySelector(element).scrollIntoView({
        behavior: 'smooth',
    })

參考資料

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/X4quZULOFgjC1Nk1zNzFyw