常用代码片段
杂记
收集开发中的一些常用代码片段
防抖
ts
/**
* @description 函数防抖
* @param {Function} method 延时调用函数
* @param {Number} wait 延迟时长
* @param {Boolean} immediate 立即执行选项
*/
export const Ddebounce = <T extends (...args: any[]) => any>(
method: T,
wait: number,
immediate: boolean
) => {
if (typeof method !== 'function') {
throw new TypeError('Expected a function')
}
let timeout: ReturnType<typeof setTimeout> | null = null
// Ddebounce函数为返回值
// 使用Async/Await处理异步,如果函数异步执行,等待setTimeout执行完,拿到原函数返回值后将其返回
// args为返回函数调用时传入的参数,传给method
let Ddebounce = async (...args: Parameters<T>): Promise<ReturnType<T>> => {
return new Promise((resolve) => {
// 用于记录原函数执行结果
let result: ReturnType<T>
// 将method执行时this的指向设为 debounce 返回的函数被调用时的this指向
let context = this
// 如果存在定时器则将其清除
if (timeout) {
clearTimeout(timeout)
}
// 立即执行需要两个条件,一是immediate为true,二是timeout未被赋值或被置为null
if (immediate) {
// 如果定时器不存在,则立即执行,并设置一个定时器,wait毫秒后将定时器置为null
// 这样确保立即执行后wait毫秒内不会被再次触发
let callNow = !timeout
timeout = setTimeout(() => {
timeout = null
}, wait)
// 如果满足上述两个条件,则立即执行并记录其执行结果
if (callNow) {
result = method.apply(context, args)
resolve(result)
}
} else {
// 如果immediate为false,则等待函数执行并记录其执行结果
// 并将Promise状态置为fullfilled,以使函数继续执行
timeout = setTimeout(() => {
// args是一个数组,所以使用fn.apply
// 也可写作method.call(context, ...args)
result = method.apply(context, args)
resolve(result)
}, wait)
}
})
}
// 在返回的 Ddebounce 函数上添加取消方法
// Ddebounce.cancel = function () {
// clearTimeout(timeout)
// timeout = null
// }
return Ddebounce
}
javascript
const run = function () {
console.log("i'm run")
}
window.addEventListener('resize', Ddebounce(run, 2000, false))
节流
ts
/**
* 节流
* @param func 回调函数
* @param delay 延迟时间
*/
export const Dthrottle = <T extends (...args: any[]) => void>(func: T, delay: number) => {
let timer: ReturnType<typeof setTimeout> | null = null
return function (this: ThisParameterType<T>, ...args: Parameters<T>) {
const context = this
if (!timer) {
timer = setTimeout(function () {
func.apply(context, args)
timer = null
}, delay)
}
}
}
javascript
// 假设有一个需要被节流的函数
function expensiveOperation() {
console.log('Running expensive operation...')
// 这里可以是一些耗时较长的操作
}
// 使用 throttle 函数对 expensiveOperation 进行节流
const throttledFunc = throttle(expensiveOperation, 1000)
// 模拟频繁调用 expensiveOperation 函数
setInterval(function () {
throttledFunc()
}, 500)
柯里化
ts
function selfCurryFn<T extends Function>(fn: T): T {
const fnLen = fn.length
function curry(...args: any[]): any {
const argLen = args.length
if (argLen < fnLen) {
return function otherCurry(...args2: any[]): any {
return curry(...args.concat(args2))
}
} else {
return fn(...args)
}
}
return curry as T
}
ts
// 示例用法:
function sum(a: number, b: number, c: number): number {
return a + b + c
}
const curriedSum = selfCurryFn(sum)
console.log(curriedSum(1)(2)(3))
console.log(curriedSum(1, 2)(3))
console.log(curriedSum(1)(2, 3))
console.log(curriedSum(1, 2, 3))
拷贝
typescript
function deepClone<T>(obj: T, clonedMap = new WeakMap()): T {
// 检查是否已经拷贝过该对象,避免循环引用导致的无限递归
if (clonedMap.has(obj)) {
return clonedMap.get(obj) as T
}
let newObj: T
// 特殊类型的处理
if (obj instanceof Date) {
newObj = new Date(obj.getTime()) as T
} else if (obj instanceof RegExp) {
newObj = new RegExp(obj) as T
} else if (typeof obj === 'function') {
// 自定义需要特殊处理的函数类型
// newObj = obj.bind(null) as T;
newObj = obj as T
} else if (Array.isArray(obj)) {
newObj = [] as unknown as T
} else if (obj && typeof obj === 'object') {
newObj = {} as T
} else {
return obj
}
// 将当前对象添加到已拷贝的对象 Map 中
clonedMap.set(obj, newObj)
// 遍历对象的属性进行深拷贝
for (let key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
newObj[key] = deepClone(obj[key], clonedMap)
}
}
return newObj
}
javascript
// 基本类型
const num = 123
const str = 'hello'
const bool = true
console.log(deepClone(num)) // 123
console.log(deepClone(str)) // 'hello'
console.log(deepClone(bool)) // true
// 数组
const arr = [1, 2, [3, 4], { a: 5 }]
const clonedArr = deepClone(arr)
console.log(clonedArr) // [1, 2, [3, 4], { a: 5 }]
console.log(arr === clonedArr) // false
clonedArr[0] = 100
console.log(clonedArr) // [100, 2, [3, 4], { a: 5 }]
console.log(arr) // [1, 2, [3, 4], { a: 5 }]
clonedArr[2][0] = 300
console.log(clonedArr) // [100, 2, [300, 4], { a: 5 }]
console.log(arr) // [1, 2, [300, 4], { a: 5 }]
// 对象
const obj = { x: 1, y: { z: 2 } }
const clonedObj = deepClone(obj)
console.log(clonedObj) // { x: 1, y: { z: 2 } }
console.log(obj === clonedObj) // false
clonedObj.x = 100
console.log(clonedObj) // { x: 100, y: { z: 2 } }
console.log(obj) // { x: 1, y: { z: 2 } }
clonedObj.y.z = 200
console.log(clonedObj) // { x: 100, y: { z: 200 } }
console.log(obj) // { x: 1, y: { z: 200 } }
// 循环引用
const circularObj = { prop: null }
circularObj.prop = circularObj
const clonedCircularObj = deepClone(circularObj)
console.log(clonedCircularObj) // { prop: [Circular] }
console.log(clonedCircularObj.prop === clonedCircularObj) // true
手写 call、apply 及 bind 函数
javascript
Function.prototype.Dcall = function (context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
var context = context || window
context.say = this
var args = []
for (let i = 1; i < arguments.length; i++) {
args.push('arguments[' + i + ']')
}
var result = eval('context.say(' + args + ')')
delete context.say
return result
}
javascript
Function.prototype.Dapply = function (context, arr) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
var context = context || window
var result
context.fn = this
if (!arr) {
result = context.fn()
} else {
var args = []
for (let i = 0; i < arr.length; i++) {
args.push('arr[' + i + ']')
}
result = eval('context.fn(' + args + ')')
}
return result
}
javascript
Function.prototype.Dbind = function (context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
var self = this
var args = Array.prototype.slice.call(arguments, 1)
return function () {
var bindArgs = Array.prototype.slice.call(arguments)
return self.apply(context, args.concat(bindArgs))
}
}
javascript
// 示例函数
function greet() {
console.log(`Hello, ${this.name}!`)
}
// 1. 使用 Dcall 方法调用函数,并指定上下文对象和参数
const person1 = { name: 'Alice' }
greet.Dcall(person1) // 输出:Hello, Alice!
// 2. 使用 Dapply 方法调用函数,并指定上下文对象和参数数组
const person2 = { name: 'Bob' }
const args = ['Nice to meet you!']
greet.Dapply(person2, args) // 输出:Hello, Bob!
// 3. 使用 Dbind 方法创建新函数,预先绑定上下文和参数
const person3 = { name: 'Charlie' }
const greetPerson3 = greet.Dbind(person3)
greetPerson3() // 输出:Hello, Charlie!
new
javascript
Function.prototype.Dnew = function (fn, ...args) {
var obj = Object.create(fn.prototype)
var ret = fn.apply(obj, args)
return ret instanceof Object ? ret : obj
}
// 或
Function.prototype.DDnew = function () {
var obj = {}
var Constructor = Array.prototype.shift.call(arguments)
obj.__proto__ = Constructor.prototype
var result = Constructor.call(obj, arguments)
return result instanceof Object ? result : obj
}
instanceof
javascript
{
function new_instance_of(leftVaule, rightVaule) {
let rightProto = rightVaule.prototype
leftVaule = leftVaule.__proto__
while (true) {
if (leftVaule === null) return false
if (leftVaule === rightProto) return true
leftVaule = leftVaule.__proto__
}
}
}
{
function new_instance_of(leftVaule, rightVaule) {
let proto = Object.getPrototypeOf(leftVaule)
while (true) {
if (proto == null) return false
if (proto === rightVaule.prototype) return true
proto = Object.getPrototypeOf(proto)
}
}
}
解析 URL Params 为对象
ts
function parseParam(url: string): Record<string, any> | null {
const paramsMatch = /.+\?(.+)$/.exec(url)
if (!paramsMatch) {
return null // 处理无效的 URL
}
const paramsStr = paramsMatch[1]
const paramsArr = paramsStr.split('&')
const paramsMap = new Map<string, any>()
for (const param of paramsArr) {
if (/=/.test(param)) {
const [key, val] = param.split('=')
const decodedVal = decodeURIComponent(val)
let parsedVal: string | number | boolean = decodedVal
if (/^\d+$/.test(decodedVal)) {
parsedVal = parseFloat(decodedVal)
} else if (decodedVal === 'true') {
parsedVal = true
} else if (decodedVal === 'false') {
parsedVal = false
}
if (paramsMap.has(key)) {
const existingVal = paramsMap.get(key)
if (Array.isArray(existingVal)) {
paramsMap.set(key, [...existingVal, parsedVal])
} else {
paramsMap.set(key, [existingVal, parsedVal])
}
} else {
paramsMap.set(key, parsedVal)
}
} else {
paramsMap.set(param, true)
}
}
const paramsObj: Record<string, any> = {}
for (const [key, value] of paramsMap.entries()) {
paramsObj[key] = value
}
return paramsObj
}
js
const url = 'https://example.com/?name=wudi&age=27&interests=programming&interests=music'
const parsedParams = parseParam(url)
console.log(parsedParams)
// Output: { name: "wudi", age: 27, interests: ["programming", "music"] }
获取URL的中参数
ts
export function getQueryString(param: string): string {
const queryParams = new URLSearchParams(window.location.search)
const value = queryParams.get(param)
return value || ''
}
js
// 示例用法:
const paramName = 'name'
const paramValue = getQueryString(paramName)
console.log(paramValue)
// Output: 根据实际 URL 查询参数的值,如果存在则输出相应的值,否则输出空字符串 ''
时间格式化
ts
type FormatToken =
| 'YY'
| 'YYYY'
| 'M'
| 'MM'
| 'D'
| 'DD'
| 'H'
| 'HH'
| 'I'
| 'II'
| 'S'
| 'SS'
| 'W'
| 'WW'
const formatMap: Map<FormatToken, (date: Date) => string> = new Map([
['YY', (date: Date) => ('' + date.getFullYear()).substr(2)],
['YYYY', (date: Date) => date.getFullYear().toString()],
['M', (date: Date) => (date.getMonth() + 1).toString()],
['MM', (date: Date) => (date.getMonth() + 1).toString().padStart(2, '0')],
['D', (date: Date) => date.getDate().toString()],
['DD', (date: Date) => date.getDate().toString().padStart(2, '0')],
['H', (date: Date) => date.getHours().toString()],
['HH', (date: Date) => date.getHours().toString().padStart(2, '0')],
['I', (date: Date) => date.getMinutes().toString()],
['II', (date: Date) => date.getMinutes().toString().padStart(2, '0')],
['S', (date: Date) => date.getSeconds().toString()],
['SS', (date: Date) => date.getSeconds().toString().padStart(2, '0')],
[
'W',
(date: Date) => `星期${['日', '一', '二', '三', '四', '五', '六'][date.getDay()]}`,
],
[
'WW',
(date: Date) =>
['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][
date.getDay()
],
],
])
// format: yyyy/mm/dd hh:ii:ss(2019/07/24 09:45:43) yy/m/d hh:ii:ss(19/07/24 09:45:43) yyyy/mm/dd w(2019/07/24 星期三) mm/dd/yyyy(07/24/2019)
export function formatTime(
time?: string | number,
format: string = 'yyyy-mm-dd'
): string {
const date = time ? new Date(time) : new Date()
return format.replace(
/(YY){1,2}|M{1,2}|D{1,2}|H{1,2}|I{1,2}|S{1,2}|W{1,2}/gi,
(token) => {
const formatter = formatMap.get(token as FormatToken)
return formatter ? formatter(date) : token
}
)
}
js
// 示例用法:
const currentTime = Date.now()
const formattedTime = formatTime(currentTime, 'yyyy-mm-dd HH:II:SS')
console.log(formattedTime)
// Output: 根据当前时间生成的格式化后的时间字符串,如 "2023-08-25 09:30:15"
// iOS 解析 YYYY-MM-DD HH:mm:ss 这种日期格式会报错 Invalid Date
// 从代码习惯上, 建议使用 /
日期格式化
js
function getNowFormatDate() {
return new Date().toLocaleString() + '.' + new Date().getMilliseconds()
}
数组扁平化
javascript
/**
* @method 数组扁平化
* @param {*} arry
*/
export const deepFlatten = (arr) => {
return arr
.toString()
.split(',')
.map((item) => +item)
// or
// return [].concat(...arr.map(item => (Array.isArray(item) ? deepFlatten(item) : item)));
}
判断类型
ts
export function getType(obj: any): string {
const objectType = Object.prototype.toString.call(obj)
const matchResult = objectType.match(/\s([a-zA-Z]+)/)
if (matchResult) {
return matchResult[1].toLowerCase()
}
throw new Error('Failed to determine object type')
}
js
// 示例用法:
const examples = [
123,
'Hello',
true,
[],
{},
null,
undefined,
new Date(),
function () {},
/regex/,
Symbol('symbol'),
]
examples.forEach((example, index) => {
const type = getType(example)
console.log(`Example ${index + 1}:`, example)
console.log(`Type:`, type)
console.log('--------------------')
})
// Example 1: 123
// Type: number
// --------------------
// Example 2: Hello
// Type: string
// --------------------
// Example 3: true
// Type: boolean
// --------------------
// Example 4: []
// Type: array
// --------------------
// Example 5: {}
// Type: object
// --------------------
// Example 6: null
// Type: null
// --------------------
// Example 7: undefined
// Type: undefined
// --------------------
// Example 8: Fri Aug 25 2023 14:14:21 GMT+0800 (中国标准时间)
// Type: date
// --------------------
// Example 9: ƒ () {}
// Type: function
// --------------------
// Example 10: /regex/
// Type: regexp
// --------------------
// Example 11: Symbol(symbol)
// Type: symbol
// --------------------
html 转义
javascript
export const escapeHtml = (str) => {
if (!str) return
str = str.replace(/&/g, '&')
str = str.replace(/</g, '<')
str = str.replace(/>/g, '>')
str = str.replace(/“/g, '&quto;')
str = str.replace(/'/g, ''')
return str
}
等待函数
ts
export function wait(milliseconds: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, milliseconds))
}
js
// Usage example:
async function delayedAction() {
console.log('Start execution')
await wait(2000)
console.log('Executed after a delay of 2 seconds')
}
delayedAction()
// Output:
// Start execution
// Executed after a delay of 2 seconds
对象判空
注:永远不要使用构造函数创建对象
ts
function isEmpty1(obj: Record<string, any>): boolean {
return JSON.stringify(obj) === '{}'
}
function isEmpty2(obj: Record<string, any>): boolean {
return Object.keys(obj).length === 0
}
function isEmpty3(obj: Record<string, any>): boolean {
return Object.getOwnPropertyNames(obj).length === 0
}
function isEmpty4(obj: Record<string, any>): boolean {
let flag = true
for (const key in obj) {
if (key) {
flag = false
break
}
}
return flag
}
function isEmpty5(obj: Record<string, any>): boolean {
return Reflect.ownKeys(obj).length === 0 && obj.constructor === Object
}
function isEmpty6(obj: Record<string, any>): boolean {
return (
Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj)).length === 0
)
}
function isEmpty7(value: any): boolean {
return value && Object.keys(value).length === 0 && value.constructor === Object
}
function isEmpty8(value: any): boolean {
return (
Object.prototype.toString.call(value) === '[object Object]' &&
JSON.stringify(value) === '{}'
)
}
const key = Symbol('key')
const obj: Record<symbol, string> = {
[key]: 'value',
}
console.log('[1], obj is empty:', isEmpty1(obj))
console.log('[2], obj is empty:', isEmpty2(obj))
console.log('[3], obj is empty:', isEmpty3(obj))
console.log('[4], obj is empty:', isEmpty4(obj))
console.log('[5], obj is empty:', isEmpty5(obj))
console.log('[6], obj is empty:', isEmpty6(obj))
console.log('[7], obj is empty:', isEmpty7(obj))
console.log('[8], obj is empty:', isEmpty8(obj))
// [1], obj is empty: true
// [2], obj is empty: true
// [3], obj is empty: true
// [4], obj is empty: true
// [5], obj is empty: false
// [6], obj is empty: false
// [7], obj is empty: true
// [8], obj is empty: true
js
// Lodash
_.isEmpty({})
js
// jQuery
jQuery.isEmptyObject({})
检查函数是否是promise
javascript
// 可先看vue源码实现(不严谨,但是够用)
function isDef(v) {
return v !== undefined && v !== null
}
function isPromise(fn) {
return isDef(fn) && typeof fn.then === 'function' && typeof fn.catch === 'function'
}
console.log(isPromise(new Promise())) // true
// graphql-js 的实现方式
function isPromise_graphql(fn) {
return Boolean(fn && typeof fn.then === 'function')
}
// 利用 instanceof
function isPromise_instanceof(fn) {
return fn instanceof Promise
}
// 利用 prototype
function isPromise_prototype(fn) {
return fn && Object.prototype.toString.call(fn) === '[object Promise]'
}
检查函数是否是一个生成器
javascript
const test = function* () {
yield undefined
}
console.log(x.constructor.name === 'GeneratorFunction') // true
// 或者
const GeneratorFunction = function* () {
yield undefined
}.constructor
console.log(test instanceof GeneratorFunction) // true
// 需要注意
foo = test.bind(bar)
console.log(foo instanceof GeneratorFunction) // false
判断浏览器运行环境
ts
/**
* 判断浏览器运行环境
*/
export const BrowserType = () => {
// 权重:系统 + 系统版本 > 平台 > 内核 + 载体 + 内核版本 + 载体版本 > 外壳 + 外壳版本
const ua = navigator.userAgent.toLowerCase()
// const ua = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3872.0 Safari/537.36 Edg/78.0.244.0'.toLowerCase();
// const ua = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3314.0 Safari/537.36 SE 2.X MetaSr 1.0'.toLowerCase();
const testUa = (regexp: RegExp) => regexp.test(ua)
const testVs = (regexp: RegExp) =>
ua
.match(regexp)
?.toString()
.replace(/[^0-9|_.]/g, '')
.replace(/_/g, '.') ?? ''
// 系统
let system = 'unknow'
if (testUa(/windows|win32|win64|wow32|wow64/g)) {
system = 'windows' // windows系统
} else if (testUa(/macintosh|macintel/g)) {
system = 'macos' // macos系统
} else if (testUa(/x11/g)) {
system = 'linux' // linux系统
} else if (testUa(/android|adr/g)) {
system = 'android' // android系统
} else if (testUa(/ios|iphone|ipad|ipod|iwatch/g)) {
system = 'ios' // ios系统
}
// 系统版本
let systemVs = 'unknow'
if (system === 'windows') {
if (testUa(/windows nt 5.0|windows 2000/g)) {
systemVs = '2000'
} else if (testUa(/windows nt 5.1|windows xp/g)) {
systemVs = 'xp'
} else if (testUa(/windows nt 5.2|windows 2003/g)) {
systemVs = '2003'
} else if (testUa(/windows nt 6.0|windows vista/g)) {
systemVs = 'vista'
} else if (testUa(/windows nt 6.1|windows 7/g)) {
systemVs = '7'
} else if (testUa(/windows nt 6.2|windows 8/g)) {
systemVs = '8'
} else if (testUa(/windows nt 6.3|windows 8.1/g)) {
systemVs = '8.1'
} else if (testUa(/windows nt 10.0|windows 10/g)) {
systemVs = '10'
}
} else if (system === 'macos') {
systemVs = testVs(/os x [\d._]+/g)
} else if (system === 'android') {
systemVs = testVs(/android [\d._]+/g)
} else if (system === 'ios') {
systemVs = testVs(/os [\d._]+/g)
}
// 平台
let platform = 'unknow'
if (system === 'windows' || system === 'macos' || system === 'linux') {
platform = 'desktop' // 桌面端
} else if (system === 'android' || system === 'ios' || testUa(/mobile/g)) {
platform = 'mobile' // 移动端
}
// 内核和载体
let engine = 'unknow'
let supporter = 'unknow'
if (testUa(/applewebkit/g)) {
engine = 'webkit' // webkit内核
if (testUa(/edg/g)) {
supporter = 'edge' // edge浏览器
} else if (testUa(/opr/g)) {
supporter = 'opera' // opera浏览器
} else if (testUa(/chrome/g)) {
supporter = 'chrome' // chrome浏览器
} else if (testUa(/safari/g)) {
supporter = 'safari' // safari浏览器
}
} else if (testUa(/gecko/g) && testUa(/firefox/g)) {
engine = 'gecko' // gecko内核
supporter = 'firefox' // firefox浏览器
} else if (testUa(/presto/g)) {
engine = 'presto' // presto内核
supporter = 'opera' // opera浏览器
} else if (testUa(/trident|compatible|msie/g)) {
engine = 'trident' // trident内核
supporter = 'iexplore' // iexplore浏览器
}
// 内核版本
let engineVs = 'unknow'
if (engine === 'webkit') {
engineVs = testVs(/applewebkit\/[\d._]+/g)
} else if (engine === 'gecko') {
engineVs = testVs(/gecko\/[\d._]+/g)
} else if (engine === 'presto') {
engineVs = testVs(/presto\/[\d._]+/g)
} else if (engine === 'trident') {
engineVs = testVs(/trident\/[\d._]+/g)
}
// 载体版本
let supporterVs = 'unknow'
if (supporter === 'chrome') {
supporterVs = testVs(/chrome\/[\d._]+/g)
} else if (supporter === 'safari') {
supporterVs = testVs(/version\/[\d._]+/g)
} else if (supporter === 'firefox') {
supporterVs = testVs(/firefox\/[\d._]+/g)
} else if (supporter === 'opera') {
supporterVs = testVs(/opr\/[\d._]+/g)
} else if (supporter === 'iexplore') {
supporterVs = testVs(/(msie [\d._]+)|(rv:[\d._]+)/g)
} else if (supporter === 'edge') {
supporterVs = testVs(/edg\/[\d._]+/g)
}
// 外壳和外壳版本
let shell = ''
let shellVs = ''
if (testUa(/micromessenger/g)) {
shell = 'wechat' // 微信浏览器
shellVs = testVs(/micromessenger\/[\d._]+/g)
} else if (testUa(/qqbrowser/g)) {
shell = 'qq' // QQ浏览器
shellVs = testVs(/qqbrowser\/[\d._]+/g)
} else if (testUa(/ucbrowser/g)) {
shell = 'uc' // UC浏览器
shellVs = testVs(/ucbrowser\/[\d._]+/g)
} else if (testUa(/qihu 360se/g)) {
shell = '360' // 360浏览器(无版本)
} else if (testUa(/2345explorer/g)) {
shell = '2345' // 2345浏览器
shellVs = testVs(/2345explorer\/[\d._]+/g)
} else if (testUa(/metasr/g)) {
shell = 'sougou' // 搜狗浏览器(无版本)
} else if (testUa(/lbbrowser/g)) {
shell = 'liebao' // 猎豹浏览器(无版本)
} else if (testUa(/maxthon/g)) {
shell = 'maxthon' // 遨游浏览器
shellVs = testVs(/maxthon\/[\d._]+/g)
}
return Object.assign(
{
/** webkit gecko presto trident */
engine,
engineVs,
/** desktop mobile */
platform,
/** chrome safari firefox opera iexplore edge */
supporter,
supporterVs,
/** windows macos linux android ios */
system,
systemVs,
},
shell === ''
? {}
: {
/** wechat qq uc 360 2345 sougou liebao maxthon */
shell,
shellVs,
}
)
}
function handleUpdateBrowser() {
const { supporter, shell = '' } = BrowserType()
// Chrome: https://www.google.cn/intl/zh-CN/chrome/
// Microsoft Edge: https://www.microsoft.com/zh-cn/edge
// QQ: https://browser.qq.com/
// 搜狗浏览器: https://ie.sogou.com/
// IE: https://www.microsoft.com/zh-cn/edge
// Firefox: http://www.firefox.com.cn/
// Safari: https://support.apple.com/zh-cn/HT204416
// Opera: https://www.opera.com/zh-cn
// MiuiBrowser: https://www.google.cn/intl/zh-CN/chrome/
// 其它浏览器: https://www.google.cn/intl/zh-CN/chrome/
// chrome safari firefox opera iexplore edge qq sougou
if (supporter || ['qq', 'sougou'].includes(shell)) {
switch (supporter) {
case 'chrome':
shell === 'sougou'
? window.open('https://ie.sogou.com/')
: window.open('https://www.google.cn/intl/zh-CN/chrome/')
break
case 'safari':
window.open('https://support.apple.com/zh-cn/HT204416')
break
case 'firefox':
window.open('http://www.firefox.com.cn/')
break
case 'opera':
window.open('https://www.opera.com/zh-cn')
break
case 'edge':
case 'iexplore':
window.open('https://www.microsoft.com/zh-cn/edge')
break
default:
shell === 'qq'
? window.open('https://browser.qq.com/')
: shell === 'sougou'
? window.open('https://ie.sogou.com/')
: window.open('https://www.google.cn/intl/zh-CN/chrome/')
break
}
} else {
window.open('https://www.google.cn/intl/zh-CN/chrome/')
}
}
生成 -0
javascript
// one
// 首先创建一个8位的ArrayBuffer
const buffer = new ArrayBuffer(8)
// 创建DataView对象操作buffer
const dataView = new DataView(buffer)
// 将第1个字节设置为0x80,即最高位为1
dataView.setUint8(0, 0x80)
// 将buffer内容当做Float64类型返回
console.log(dataView.getFloat64(0)) // -0
// two
console.log(0 * -1) // -0
H5(ios)-在点击输入框,出现键盘后,弹出层被顶上去,而光标还停留在原处,即出现错位情况
javascript
{
// 单个input(textarea)
$('input.van-field__control, textarea.van-field__control').blur(function () {
setTimeout(function () {
var currentPosition = document.documentElement.scrollTop || document.body.scrollTop
window.scrollTo(0, currentPosition) //页面向上滚动
}, 200)
})
// 多个input(textarea)
$(function () {
var setTimerTop = 0
$(document)
.on('blur', 'input.van-field__control, textarea.van-field__control', function () {
event.preventDefault()
setTimerTop = setTimeout(function () {
window.scrollBy(0, 5) // 页面向上滚动
window.scrollBy(0, -5)
}, 500)
})
.on('focus', 'input.van-field__control, textarea.van-field__control', function () {
clearTimeout(setTimerTop)
})
})
// 多个input(textarea)-iframe情况
$(function () {
var setTimerTop = 0
$(document)
.on('blur', 'input.van-field__control, textarea.van-field__control', function () {
event.preventDefault()
setTimerTop = setTimeout(function () {
parent.scrollBy(0, 5) // 页面向上滚动
parent.scrollBy(0, -5)
$('#hide-area-cb').focus()
}, 500)
})
.on('focus', 'input.van-field__control, textarea.van-field__control', function () {
clearTimeout(setTimerTop)
})
.on('focus', 'input.van-field__control[disabled]', function () {
setTimerTop = setTimeout(function () {
parent.scrollBy(0, 5) // 页面向上滚动
parent.scrollBy(0, -5)
}, 500)
})
})
}
实现数字金额转大写金额
ts
export function convertToChineseAmount(amount: number): string {
const chineseNumbers: string[] = [
'',
'壹',
'贰',
'叁',
'肆',
'伍',
'陆',
'柒',
'捌',
'玖',
]
const chineseUnits: string[] = ['', '拾', '佰', '仟', '万', '亿', '兆']
if (amount === 0) {
return '零元'
}
let integerPart = Math.floor(amount)
let decimalPart = Math.round((amount - integerPart) * 100)
const integerPartStr = convertIntegerPart(integerPart, chineseNumbers, chineseUnits)
const decimalPartStr = convertDecimalPart(decimalPart, chineseNumbers)
let result = ''
if (integerPartStr !== '') {
result += integerPartStr + '元'
}
if (decimalPartStr !== '') {
result += decimalPartStr
} else {
result += '整'
}
return result
}
function convertIntegerPart(
amount: number,
chineseNumbers: string[],
chineseUnits: string[]
): string {
let result = ''
let unitIndex = 0
let isFirstDigitZero = true
while (amount > 0) {
const digit = amount % 10
if (digit !== 0) {
const number = chineseNumbers[digit]
const unit = chineseUnits[unitIndex % 7]
result = number + unit + result
isFirstDigitZero = false
} else {
if (!isFirstDigitZero) {
result = '零' + result
}
}
unitIndex++
amount = Math.floor(amount / 10)
}
return result
}
function convertDecimalPart(amount: number, chineseNumbers: string[]): string {
if (amount === 0) {
return ''
}
const digit1 = Math.floor(amount / 10)
const digit2 = amount % 10
let result = ''
if (digit1 !== 0) {
result += chineseNumbers[digit1] + '角'
}
if (digit2 !== 0) {
result += chineseNumbers[digit2] + '分'
}
return result
}
js
// 示例用法:
const amount1 = 123456789.12
const amount2 = 1000.01
const amount3 = 0.5
console.log(convertToChineseAmount(amount1)) // Output: "壹亿贰千叁百肆拾伍万陆仟柒佰捌拾玖元壹角贰分"
console.log(convertToChineseAmount(amount2)) // Output: "壹仟元零壹分"
console.log(convertToChineseAmount(amount3)) // Output: "伍角"
平均数
javascript
// 平均数
const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length
console.log(average(...[1, 2, 3])) // 2
console.log(average(1, 2, 3)) // 2
平滑滚动至顶部
javascript
const scrollToTop = () => {
const c = document.documentElement.scrollTop || document.body.scrollTop
if (c > 0) {
window.requestAnimationFrame(scrollToTop)
window.scrollTo(0, c - c / 8)
}
}
滚动到指定元素区域
javascript
const smoothScroll = (element) =>
document.querySelector(element).scrollIntoView({
behavior: 'smooth',
})
smoothScroll('#fooBar')
npm 获取版本号
javascript
import axios from 'axios'
async function getPackageVersion(packageName, versionRange = '') {
const registryUrl = 'https://registry.npmjs.org'
const encodedPackageName = encodeURIComponent(packageName).replace(/^%40/, '@')
const url = `${registryUrl}/${encodedPackageName}/${versionRange}`
try {
const response = await axios.get(url)
return response.data.version
} catch (error) {
console.error(`Failed to fetch package version for '${packageName}':`, error)
throw error
}
}
;(async () => {
try {
const packageName = 'axios'
const versionRange = 'latest' // ^0.21.4
const packageVersion = await getPackageVersion(packageName, versionRange)
console.log(
`Version of ${packageName} satisfying the range "${versionRange}": ${packageVersion}`
)
} catch (error) {
console.log('🚀 ~ file: getPackageVersion ~ error:', error)
}
})()
判断函数是否 async
js
function isAsyncFunction(func) {
if (typeof func !== 'function') {
throw new Error('Invalid argument: func must be a function')
}
return func[Symbol.toStringTag] === 'AsyncFunction'
}
js
console.log(
'function ',
isAsyncFunction(() => {})
)
console.log(
'async function ',
isAsyncFunction(async () => {})
)
console.log(
'function Promise ',
isAsyncFunction(() => {
return new Promise(() => {})
})
)