常用方法
生成指定范围内的随机数
Math.floor(Math.random() * (max - min + 1) + min)
数组去重
// 方法1:利用 es6 的 Set 类型: Set 类型没有重复的数据,结构类似数组
let arr1 = [1, 2, 2, 2, 3]
let arr2 = Array.from(new Set(arr1))
// Array.from 会把类数组对象都转为数组
// 或者:
let arr3 = [...new Set(arr1)]
// 方法2:hash 去重,利用关联数组下标唯一性或对象键的唯一性进行去重
let arr1 = [1, 2, 3, 4, 2, 3, 5, 7, 5, 8]
let arr2 = []
let arr3 = []
for(const element of arr1) {
if(!arr2[element]) {
arr2[element] = 1
arr3.push(element)
}
}
// 方法3:根据某个字段去重
function arrayUnique (arr, field = 'id') {
return arr.reduce((all, next) => all.some(item => item[field] === next[field]) ? all : [...all, next], [])
}
深拷贝
// 方法一
const copy = JSON.parse(JSON.stringify(obj))
// 方法二
import { cloneDeep } from 'lodash-es'
const copy = cloneDeep(obj)
// 方法三: 写递归遍历
function clone(o) {
const temp = {}
for (const key in o) {
if (typeof o[key] === 'object') {
temp[key] = clone(o[key])
} else {
temp[key] = o[key]
}
}
return temp
}
判断类型
// 方法一
import { isArray, isFunction, isNull } from 'lodash-es'
// 方法二
function typeOf (obj) {
const typeMap = {
'[object Boolean]': 'boolean',
'[object Number]': 'number',
'[object String]': 'string',
'[object Function]': 'function',
'[object Array]': 'array',
'[object Date]': 'date',
'[object RegExp]': 'regExp',
'[object Undefined]': 'undefined',
'[object Null]': 'null',
'[object Object]': 'object',
}
return typeMap[Object.prototype.toString.call(obj)]
}
判断两个数据是否相等
// 方法一
import { isEqual } from 'lodash-es'
// 方法二
function equalsObj (oldObj, newObj) {
if (oldObj === newObj) return true
if (typeOf(oldObj) !== typeOf(newObj)) return false // typeOf 是自定义函数
if (typeOf(oldObj) === 'object') {
if (Object.keys(oldObj).length !== Object.keys(newObj).length) return false
for(const key in oldObj) {
if (!newObj.hasOwnProperty(key)) return false
if (!equalsObj(oldObj[key], newObj[key])) return false
}
return true
} else if (typeOf(oldObj) === 'array') {
if (oldObj.length !== newObj.length) return false
for (const i in oldObj) {
if (!equalsObj(oldObj[i], newObj[i])) return false
}
return true
} else {
return oldObj.toString() === newObj.toString()
}
}
isEqual(oldObj, newObj)
节流
规定函数在某时间段内最多执行一次,一般用于鼠标移动、滚动屏幕、轮询加载等场景中,会多次触发 throttle 函数
// 方法一
import { throttle } from 'lodash-es'
// 方法二
// immediately - 首次是否执行
function throttle(fun: (...args)=>void, time = 200, immediately = false) {
let startTime = Date.now(), donow = immediately;
return (...args) => {
const endTime = Date.now();
if (donow) {
fun(..arg);
donow = false;
}
if (endTime - startTime >= time) {
fun(..arg);
startTime = endTime;
}
}
}
防抖
规定函数至少间隔多久执行,函数执行过一次后,在 n 秒内不能再次执行,否则推迟函数执行,一般用于监测鼠标移动结束、滚动屏幕结束、拖拽终止更新等场景中
// 方法一
import { debounce } from 'lodash-es'
// 方法二
function debounce (func, delay = 300) {
let timer = null
return (...args) => {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
func(...args)
}, delay)
}
}
数组转树
npm i array-to-tree
const tree = arrayToTree(dataTwo, {
parentProperty: 'parent', // 默认 parent_id
customID: '_id' // 默认 id
});
树转数组
function tree2Array(tree) {
const temp = []
const out = []
temp.push(tree)
const obj = deepCopy(tree)
delete obj['children']
out.push(obj)
// 广度优先遍历
while (temp.length) {
const first = temp.shift()
const children = first.children
if(children && children.length) {
const len = first.children.length
for (let i=0; i < len; i++){
temp.push(children[i])
const obj = deepCopy(children[i])
delete obj['children']
out.push(obj)
}
}
}
return out
}
根据给定的属性路径判断属性是否存在
// eg.: hasOwnProperty(aa, 'b.c.d') hasOwnProperty(bb, 'e.1.f.0.g')
function hasOwnProperty (obj, key) {
let tag = true
const arr = key.split('.')
arr.reduce((pre, item) => {
if (pre !== undefined && Object.prototype.hasOwnProperty.call(pre, item)) {
return pre[item]
} else {
tag = false
}
}, obj)
return tag
}
中划线转驼峰
function getCamel (str) {
return str.replace(/-(\w)/, (_, c) => c ? c.toUpperCase() : '');
}
递归
// 根据某一属性值递归查找 obj[key] === value
function findItem(list, key, value) {
if (Array.isArray(list)) {
for(const item of list) {
if (typeof item === 'object' && item[key] === value) {
return item
}
if (item.children && item.children.length) {
const res = findItem(item.children, key, value)
if (res) return res
}
}
}
return null
}
根据字符串获取 query 参数
function getQueryString(key: string){
const arg: Record<string, string> = {}
if (location.href.includes('?')){
const qs = location.href.split('?')
let query = qs[1]
if (query.includes('#')){
// 如果查询字符串后存在hash值,去掉hash值
query = query.split('#')[0]
}
query.split('&').forEach((v: string) => {
const kv = v.split('=')
arg[kv[0]] = kv[1]
})
}
return arg[key]
}
js模拟发送按键事件
function dispatchKeyboard(key: string){
const keyboardEvent = new KeyboardEvent('keydown', {
code: 'F11',
keyCode: 122,
key: 'F11',
})
keyboardEvent.initEvent('keydown', true, true)
document.dispatchEvent(keyboardEvent)
}
判断是否同源
function isSameOrigin(url: string) {
if (url.startsWith('/')) {
return true
}
const regex = /^(\w+):\/\/([^/:]+)(?::(\d+))?/
const match = url.match(regex)
const matchOrigin = location.href.match(regex)
if (match && matchOrigin) {
let [, protocol1, host1, port1] = match
let [, protocol2, host2, port2] = matchOrigin
if (port1) {
port1 = '80'
}
if (port2) {
port2 = '80'
}
return protocol1 === protocol2 && host1 === host2 && port1 === port2
}
return false
}
切换全屏
function toggleFullscreen() {
const element = document.documentElement
if(element.fullscreenElement) {
document.exitFullscreen && document.exitFullscreen()
} else {
element.requestFullscreen && element.requestFullscreen()
}
}