javascript 语法基础 ECMAScript 的 Utils
Table of Contents
Number Conversion 1 2 3 4 5 6 ;(10 ).toString(2 ) ;(10 ).toString(8 ) parseInt (1010 , 2 )
throttle
函数节流
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function throttle (fn, delay = 0 ) { let last let timer return function ( ) { const now = Date .now() if (last && now < last + delay) { clearTimeout(timer) timer = setTimeout(() => { fn.apply(this , arguments ) last = now }, delay) } else { fn.apply(this , arguments ) last = now } } }
debounce
函数防抖
1 2 3 4 5 6 7 8 9 function debounce (fn, delay = 0 ) { let timer = null return function ( ) { clearTimeout(timer) timer = setTimeout(() => { fn.apply(this , arguments ) }, delay) } }
shuffle
Fisher–Yates 乱序算法
1 2 3 4 5 6 7 8 function shuffle (arr ) { let length = arr.length while (length > 1 ) { let index = Math .floor(Math .random() * length--) ;[arr[length], arr[index]] = [arr[index], arr[length]] } return arr }
randomInt 1 2 3 4 5 6 export function randomInt (min, max ) { if (min > max) { ;[min, max] = [max, min] } return Math .floor(min + Math .random() * (max - min + 1 )) }
async/await-try/catch 简化 promise 函数的异常捕获,类 node API
1 2 3 export default function errorCaptured (promiseFunc ) { return promiseFunc.then((...args ) => [null , ...args]).catch(err => [err]) }
sleep 1 export const sleep = ms => new Promise (resolve => setTimeout(resolve, ms))
isStatic
检测数据是不是除了 symbol 外的原始数据
1 2 3 4 5 6 7 8 9 10 function isStatic (value ) { const type = typeof value return ( type === 'string' || type === 'number' || type === 'boolean' || type === 'undefined' || value === null ) }
isPrimitive
检测数据是不是原始数据
1 2 3 function isPrimitive (value ) { return isStatic(value) || typeof value === 'symbol' }
isObject
判断数据是不是引用类型的数据 (例如: Array, Function, Object, Regexp, new Number(0),以及 new String(‘’))
1 2 3 4 function isObject (value ) { const type = typeof value return value !== null && (type === 'object' || type === 'function' ) }
isObjectLike
检查 value 是否是 类对象。 如果一个值是类对象,那么它不应该是 null,而且 typeof 后的结果是 “object”
1 2 3 function isObjectLike (value ) { return value !== null && typeof value === 'object' }
toString
获取数据类型,返回结果为 Number、String、Object、Array 等
1 2 3 4 function _toString (value ) { return Object .prototype.toString.call(value).slice(8 , -1 ) }
isPlainObject
判断数据是不是 Object 类型的数据
1 2 3 function isPlainObject (obj ) { return Object .prototype.toString.call(obj) === '[object Object]' }
isArray
判断数据是不是数组类型的数据
1 2 3 function isArray (value ) { return Object .prototype.toString.call(value) === '[object Array]' }
ES6
isRegExp
判断数据是不是正则对象
1 2 3 function isRegExp (value ) { return Object .prototype.toString.call(value) === '[object RegExp]' }
isDate
判断数据是不是时间对象
1 2 3 function isDate (value ) { return Object .prototype.toString.call(value) === '[object Date]' }
isNative
判断 value 是不是浏览器内置函数 内置函数 toString 后的主体代码块为 [native code] ,而非内置函数则为相关代码,所以非内置函数可以进行拷贝(toString 后掐头去尾再由 Function 转)
1 2 3 function isNative (value ) { return typeof value === 'function' && /native code/ .test(value.toString()) }
isFunction
检查 value 是不是函数
1 2 3 function isFunction (value ) { return Object .prototype.toString.call(value) === '[object Function]' }
isLength
检查 value 是否为有效的类数组长度
1 2 3 4 5 6 7 8 function isLength (value ) { return ( typeof value === 'number' && value > -1 && value % 1 === 0 && value <== Number .MAX_SAFE_INTEGER ) }
isValidArrayIndex
判断变量是否含有效的数组索引
1 2 3 4 5 function isValidArrayIndex (val: any ): boolean { const n = parseFloat (String (val)) return n >= 0 && Math .floor(n) === n && isFinite (val) }
isArrayLike
检查 value 是否是类数组 如果一个值被认为是类数组,那么它不是一个函数,并且 value.length 是个整数,大于等于 0,小于或等于 Number.MAX_SAFE_INTEGER。这里字符串也将被当作类数组。
1 2 3 function isArrayLike (value ) { return value !== null && isLength(value.length) && !isFunction(value) }
hasOwn
检查是否自身属性,而不是原型链上的
1 2 3 function hasOwnProperty (value, key ) { return Object .prototype.hasOwnProperty.call(value, key) }
isEmpty
检查 value 是否为空 如果是 null,直接返回 true;如果是类数组,判断数据长度;如果是 Object 对象,判断是否具有属性;如果是其他数据,直接返回 true
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function isEmpty (value ) { if (value === null ) { return true } if (isArrayLike(value)) { return !value.length } else if (isPlainObject(value)) { for (let key in value) { if (hasOwnProperty(value, key)) { return false } } } return true }
inBrowser
检测当前宿主环境是否是浏览器
1 2 const inBrowser = typeof window !== 'undefined'
hasProto
检查当前环境是否可以使用对象的 __proto__ 属性
1 2 3 const hasProto = '__proto__' in {}
userAgent
获取当浏览器的 user agent
1 2 const UA = inBrowser && window .navigator.userAgent.toLowerCase()
browserType
使用正则去匹配 UA 中是否包含’msie’或者’trident’这两个字符串即可判断是否为 IE 浏览器
1 2 3 4 const isIE = UA && /msie|trident/ .test(UA)const isIE9 = UA && UA.indexOf('msie 9.0' ) > 0 const isEdge = UA && UA.indexOf('edge/' ) > 0 const isChrome = UA && /chrome\/\d+/ .test(UA) && !isEdge
toString
将给定变量的值转换为 string 类型并返回
1 2 3 4 5 6 7 export function toString (val: any ): string { return val == null ? '' : typeof val === 'object' ? JSON .stringify(val, null , 2 ) : String (val) }
cached
记忆函数:缓存函数的运算结果
1 2 3 4 5 6 function cached (fn ) { const cache = Object .create(null ) return function (str ) { return cache[str] || (cache[str] = fn(str)) } }
isReserved
检测字符串是否以 $ 或者 _ 开头
1 2 3 4 5 export function isReserved (str: string ): boolean { const c = (str + '' ).charCodeAt(0 ) return c === 0x24 || c === 0x5f }
charCodeAt
从传递进来的字母序列中找到缺失的字母并返回它。 如:fearNotLetter(“abce”) 应该返回 “d”。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function fearNotLetter (str ) { let arr = [] for (let i = 0 ; i < str.length; i++) { arr.push(str.charCodeAt(i)) } for (let j = 1 ; j < arr.length; j++) { let num = arr[j] - arr[j - 1 ] if (num != 1 ) { return String .fromCharCode(arr[j] - 1 ) } } return undefined } fearNotLetter('abce' )
camelize
连字符转驼峰命名
1 2 3 4 5 6 7 8 9 const camelizeRE = /-(\w)/g function camelize (str ) { return str.replace(camelizeRE, function (_, c ) { return c ? c.toUpperCase() : '' }) } const _camelize = cached(camelize)
hyphenate
驼峰命名转横线命名:拆分字符串,使用 - 相连,并且转换为小写
1 2 3 4 5 6 7 const hyphenateRE = /\B([A-Z])/g function hyphenate (str ) { return str.replace(hyphenateRE, '-$1' ).toLowerCase() } const _hyphenate = cached(hyphenate)
capitalize
字符串首位大写
1 2 3 4 5 6 function capitalize (str ) { return str.charAt(0 ).toUpperCase() + str.slice(1 ) } const _capitalize = cached(capitalize)
extend
将属性混合到目标对象中
1 2 3 4 5 6 function extend (to, _from ) { for (const key in _from) { to[key] = _from[key] } return to }
deepClone
1 2 3 function deepClone (target ) { return JSON .parse(JSON .stringify(target)) }
Array - unique
1 2 3 function unique (arr ) { return [...new Set (arr)] }
isNaN
检查数据是否是非数字值 原生的 isNaN 会把参数转换成数字(valueof),而 null、true、false 以及长度小于等于 1 的数组(元素为非 NaN 数据)会被转换成数字,这不是我想要的。Symbol 类型的数据不具有 valueof 接口,所以 isNaN 会抛出错误,这里放在后面,可避免错误
1 2 3 4 function _isNaN (value ) { const type = typeof value return !(type === 'string' || type === 'number' ) || isNaN (v) }
Array - max
求取数组中非 NaN 数据中的最大值
1 2 3 4 5 function max (arr ) { arr = arr.filter(item => !_isNaN(item)) return arr.length ? Math .max.apply(null , arr) : undefined }
Array - min
求取数组中非 NaN 数据中的最小值
1 2 3 4 5 function min (arr ) { arr = arr.filter(item => !_isNaN(item)) return arr.length ? Math .min.apply(null , arr) : undefined }