# 优雅的取随机字符串

Math.random().toString(16).substring(2) // 13位
Math.random().toString(36).substring(2) // 11位

# 随机数

在指定的范围内生成一个随机数

const randomInRange = (min, max) => Math.random() * (max - min) + min;
// randomInRange(2,10) -> 6.0211363285087005

# 随机整数

在指定的范围内生成一个随机整数

const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
// randomIntegerInRange(0, 5) -> 2

# 数组集合

创建过去七天的数组,如果将代码中的减号换成加号,你将得到未来7天的数组集合


// 创建过去七天的数组
[...Array(7).keys()].map(days => new Date(Date.now() - 86400000 * days));

# 数组并集

/**
 * 数组并集,只支持一维数组
 * @param {Array} arrOne
 * @param {Array} arrTwo
 */
export const arrAndSet = (arrOne, arrTwo) => {
  return arrOne.concat(arrTwo.filter(v => !arrOne.includes(v)))
}

# 数组交集

/**
 * 数组交集,只支持一维数组
 * @param {Array} arrOne
 * @param {Array} arrTwo
 */
export const arrIntersection = (arrOne, arrTwo) => {
  return arrOne.filter(v => arrTwo.includes(v))
}

# 数组差集

/**
 * 数组差集,只支持一维数组
 * @param {Array} arrOne
 * @param {Array} arrTwo
 * eg: [1, 2, 3] [2, 4, 5] 差集为[1,3,4,5]
 */
export const arrDifference = (arrOne, arrTwo) => {
  return arrOne.concat(arrTwo).filter(v => !arrOne.includes(v) || !arrTwo.includes(v))
}

# 两个数组合并成一个数组对象


/**
 * 只支持两个一维数组
 * @param {Array} arrOne
 * @param {Array} arrTwo
 * @param {oneKey} oneKey 选填,如果两个都未传,直接以 arrOne 的值作为 key,arrTwo 作为 value
 * @param {twoKey} twoKey
 */
export const arrTwoToArrObj = (arrOne, arrTwo, oneKey, twoKey) => {
  if(!oneKey&&!twoKey){
    return arrOne.map((oneKey, i) => ({ [oneKey]:arrTwo[i] }))
    // 或者 return Object.assign({}, arrOne, arrTwo)
  }else{
    return arrOne.map((oneKey, i) => ({ oneKey, twoKey: arrTwo[i] }))
  }
}

# 数组对象求和

/**
 * 数组对象求和
 * @param {Object} arrObj 数组对象
 * @param {String} key 数组对应的 key 值
 */
export const arrObjSum = (obj, key) => {
  return arrObj.reduce((prev, cur) => prev + cur.key, 0)
}

# 数组合并

/**
 * 数组合并,目前合并一维
 * @param {Array} arrOne 数组
 * @param {Array} arrTwo 数组
 */
export const arrConcat = (arrOne, arrTwo) => {
  return [...arrOne, ...arrTwo]
}

# 数组求和

/**
 * 数组求和
 * @param {Array} arr 数组
 */
export const arrSum = arr => {
  return arr.reduce((prev, cur)=> {
    return prev + cur
  }, 0)
}

# 数组是否包含某值

/**
 * 数组是否包含某值
 * @param {Array} arr 数组
 * @param {}  value 值,目前只支持 String,Number,Boolean
 */
export const arrIncludeValue = (arr,  value) => {
  return arr.includes( value)
}

# 数组最大值

/**
 * 数组最大值
 * @param {Array} arr  数组
 */
export const arrMax = arr => {
  return Math.max(...arr)
}

# 数组去重

/**
 * 数组去重
 * @param {Array} arr  数组
 */
export const arrRemoveRepeat = arr => {
  return Array.from(new Set(arr))
}

# 数组排序

/**
 * 数组排序
 * @param {Array} arr  数组
 * @param {Boolean} ascendFlag   升序,默认为 true
 */
export const arrOrderAscend = (arr, ascendFlag=true) => {
  return arr.sort((a, b) => {
    return ascendFlag ? a - b : b - a
  })
}

# 表单验证

/**
 * @param {String} value
 * @param {String} verify
 */
export const formVerify = (verify, value) => {
  const regObj = {
    'email': /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/g,
    'phone': /^((\+|00)86)?1[3-9]\d{9}$/g
  }
  if (regObj[verify].test(value)) return true
}

# 检查是否是iphoneX

/**
 * 检查是否是 IphoneX
 */
export const checkIsIphoneX = () => {
  const u = navigator.userAgent;
  const isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
  if (isIOS && screen.height >= 812) {
    return true;
  }
};

# 生成随机十六进制代码(生成随机颜色)

// 生成随机十六进制代码 如:'#c618b2'

'#' + Math.floor(Math.random() * 0xffffff).toString(16).padEnd(6, '0');

# 获取两个日期之间相差的天数

const getDaysDiffBetweenDates = (dateInitial, dateFinal) => (dateFinal - dateInitial) / (1000 * 3600 * 24);
// getDaysDiffBetweenDates(new Date("2017-12-13"), new Date("2017-12-22")) -> 9

# 根据键值对创建对象

const objectFromPairs = arr => arr.reduce((a, v) => (a[v[0]] = v[1], a), {});
// objectFromPairs([['a',1],['b',2]]) -> {a: 1, b: 2}

# 对象转化为键值

const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]);
// objectToPairs({a: 1, b: 2}) -> [['a',1],['b',2]])

# 大写每个单词的首字母

const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());
// capitalizeEveryWord('hello world!') -> 'Hello World!'

# 网址参数

网址参数通过适当的正则表达式,使用 match() 来获得所有的键值对, Array.reduce() 来映射和组合成一个单一的对象。将 location.search 作为参数传递给当前 url。

const getUrlParameters = url =>
  url.match(/([^?=&]+)(=([^&]*))/g).reduce(
    (a, v) => (a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1), a), {}
  );
// getUrlParameters('http://url.com/page?name=Adam&surname=Smith') -> {name: 'Adam', surname: 'Smith'}

# 扁平化数组

const array = [1, [2, [3, 4], 5], 6, 7];
console.log(array.toString().split(',').map(ele => Number.parseInt(ele))); // => [ 1, 2, 3, 4, 5, 6, 7 ]

* 类似arr.flat()

# 获取数组中的最大值和最小值

let  numbers = [5, 458 , 120 , -215 , 228 , 400 , 122205, -85411];
let maxInNumbers = Math.max.apply(Math, numbers);
let minInNumbers = Math.min.apply(Math, numbers);

# 函数柯里化

function curry(fn) {
  if (fn.length <= 1) return fn
  const generator = (...args) => {
    if (fn.length === args.length) {
      return fn(...args)
    } else {
      return (...args2) => {
        return generator(...args, ...args2)
      }
    }
  }
  return generator
}

// let add = (a, b, c, d) => a + b + c + d
// const curriedAdd = curry(add)
// curriedAdd(5)(6)(7)(8)
// >add(5,6,7,8)
// >26

# 数据类型判断

const superTypeof = function (val) {
    let ans = typeof val;
    if (ans === 'object') {
        ans = ({}).toString.call(val).slice(8, -1).toLowerCase();
    }
    return ans;
}
/**
 superTypeof(undefined); // undefined
 superTypeof(null); // null
 superTypeof(true); // boolean
 superTypeof(1); // number
 superTypeof(''); // string
 superTypeof(Symbol(1)); // symbol
 superTypeof(function () {}); // function
 superTypeof([]); // array
 superTypeof({}); // object
 superTypeof(new Date()); // date
 superTypeof(/abc/ig); // regexp
 superTypeof(Math); // math
 superTypeof(new Error('error')); // error
 ...
 */

# 数组值

确保数组值, 使用 grid ,需要重新创建原始数据,并且每行的列长度可能不匹配, 为了确保不匹配行之间的长度相等,可以使用Array.fill方法。

let array = Array(5).fill('');
console.log(array);
// outputs (5) ["", "", "", "", ""]

# 手写promise

function myPromise(constructor){
    let self=this;
    self.status="pending" //定义状态改变前的初始状态
    self.value=undefined;//定义状态为resolved的时候的状态
    self.reason=undefined;//定义状态为rejected的时候的状态
    function resolve(value){
        //两个==="pending",保证了状态的改变是不可逆的
       if(self.status==="pending"){
          self.value=value;
          self.status="resolved";
       }
    }
    function reject(reason){
        //两个==="pending",保证了状态的改变是不可逆的
       if(self.status==="pending"){
          self.reason=reason;
          self.status="rejected";
       }
    }
    //捕获构造异常
    try{
       constructor(resolve,reject);
    }catch(e){
       reject(e);
    }
}
myPromise.prototype.then=function(onFullfilled,onRejected){
   let self=this;
   switch(self.status){
      case "resolved":
        onFullfilled(self.value);
        break;
      case "rejected":
        onRejected(self.reason);
        break;
      default:
   }
}

// let p=new myPromise(function(resolve,reject){resolve(1)});
// p.then(function(x){console.log(x)})
// 输出1

# 函数防抖

// 防抖动函数
const debounce = (fn, wait=1500, immediate) => {
    let timer;
    return function() {
        if(immediate) {
            fn.apply(this,arguments)
        }
        if(timer) clearTimeout(timer)
        timer = setTimeout(()=> {
            fn.apply(this,arguments)
        },wait)
    }
}

# 函数节流

const throttle = (fn, wait = 1500) => {
  let prev = new Date();
  return function() {
    const args = arguments;
    const now = new Date();
    if (now - prev > wait) {
      fn.apply(this, args);
      prev = new Date();
    }
  }
}

# 加强版函数节流

debounce 设置的 delay 时间结束就进行下一次操作,于是每次 debounce 都为该用户重新生成定时器,回调函数被延迟了不计其数次。频繁的延迟会导致用户迟迟得不到响应,用户同样会产生“这个页面卡死了”的观感。 为了避免弄巧成拙,我们需要借力 throttle 的思想,打造一个“有底线”的 debounce——等你可以,但我有我的原则:delay 时间内,我可以为你重新生成定时器;但只要delay的时间到了,我必须要给用户一个响应.

// fn是我们需要包装的事件回调, delay是时间间隔的阈值
function throttle(fn, delay) {
  // last为上一次触发回调的时间, timer是定时器
  let last = 0, timer = null
  // 将throttle处理结果当作函数返回

  return function () {
    // 保留调用时的this上下文
    let context = this
    // 保留调用时传入的参数
    let args = arguments
    // 记录本次触发回调的时间
    let now = +new Date()

    // 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值
    if (now - last < delay) {
    // 如果时间间隔小于我们设定的时间间隔阈值,则为本次触发操作设立一个新的定时器
       clearTimeout(timer)
       timer = setTimeout(function () {
          last = now
          fn.apply(context, args)
        }, delay)
    } else {
        // 如果时间间隔超出了我们设定的时间间隔阈值,那就不等了,无论如何要反馈给用户一次响应
        last = now
        fn.apply(context, args)
    }
  }
}

# 生成随机UID

const genUid = () => {
  let length = 20
  let soupLength = genUid.soup_.length
  let id = []
  for (let i = 0; i < length; i++) {
    id[i] = genUid.soup_.charAt(Math.random() * soupLength)
  }
  return id.join('')
}
genUid.soup_ = '!#$%()*+,-./:;=?@[]^_`{|}~ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
genUid() // ;l`yCPc9A8IuK}?N6,%}

# RGB色值生成16进制色值

const rgb2Hex = rgb => {
    let rgbList = rgb.toString().match(/\d+/g)
    let hex = '#'
    for (let i = 0, len = rgbList.length; i < len; ++i) {
      hex += ('0' + Number(rgbList[i]).toString(16)).slice(-2)
    }
    return hex
};
rgb2Hex('100, 50, 0') // '#643200'

# 颜色混合

const colourBlend = (c1, c2, ratio) => {
    ratio = Math.max(Math.min(Number(ratio), 1), 0)
    let r1 = parseInt(c1.substring(1, 3), 16)
    let g1 = parseInt(c1.substring(3, 5), 16)
    let b1 = parseInt(c1.substring(5, 7), 16)
    let r2 = parseInt(c2.substring(1, 3), 16)
    let g2 = parseInt(c2.substring(3, 5), 16)
    let b2 = parseInt(c2.substring(5, 7), 16)
    let r = Math.round(r1 * (1 - ratio) + r2 * ratio)
    let g = Math.round(g1 * (1 - ratio) + g2 * ratio)
    let b = Math.round(b1 * (1 - ratio) + b2 * ratio)
    r = ('0' + (r || 0).toString(16)).slice(-2)
    g = ('0' + (g || 0).toString(16)).slice(-2)
    b = ('0' + (b || 0).toString(16)).slice(-2)
    return '#' + r + g + b
}
colourBlend('#ff0000', '#3333ff', 0.5) // "#991a80"

# 判断是否为质数

const mathIsPrime = n => {
  if (n === 2 || n === 3) {
    return true
  }
  if (isNaN(n) || n <= 1 || n % 1 != 0 || n % 2 == 0 || n % 3 == 0) {
    return false;
  }
  for (let x = 6; x <= Math.sqrt(n) + 1; x += 6) {
    if (n % (x - 1) == 0 || n % (x + 1) == 0) {
      return false
    }
  }
  return true
}
mathIsPrime(0) // true

# 深拷贝

目前最功能最全面多类型数据深拷贝

    function deepClone(target, map = new WeakMap()) {
        const mapTag = '[object Map]';
        const setTag = '[object Set]';
        const arrayTag = '[object Array]';
        const objectTag = '[object Object]';
        const argsTag = '[object Arguments]';

        const boolTag = '[object Boolean]';
        const dateTag = '[object Date]';
        const numberTag = '[object Number]';
        const stringTag = '[object String]';
        const symbolTag = '[object Symbol]';
        const errorTag = '[object Error]';
        const regexpTag = '[object RegExp]';
        const funcTag = '[object Function]';

        const deepTag = [mapTag, setTag, arrayTag, objectTag, argsTag];


        function forEach(array, iteratee) {
            let index = -1;
            const length = array.length;
            while (++index < length) {
                iteratee(array[index], index);
            }
            return array;
        }

        function isObject(target) {
            const type = typeof target;
            return target !== null && (type === 'object' || type === 'function');
        }

        function getType(target) {
            return Object.prototype.toString.call(target);
        }

        function getInit(target) {
            const Ctor = target.constructor;
            return new Ctor();
        }

        function cloneSymbol(targe) {
            return Object(Symbol.prototype.valueOf.call(targe));
        }

        function cloneReg(targe) {
            const reFlags = /\w*$/;
            const result = new targe.constructor(targe.source, reFlags.exec(targe));
            result.lastIndex = targe.lastIndex;
            return result;
        }

        function cloneFunction(func) {
            const bodyReg = /(?<={)(.|\n)+(?=})/m;
            const paramReg = /(?<=\().+(?=\)\s+{)/;
            const funcString = func.toString();
            if (func.prototype) {
                const param = paramReg.exec(funcString);
                const body = bodyReg.exec(funcString);
                if (body) {
                    if (param) {
                        const paramArr = param[0].split(',');
                        return new Function(...paramArr, body[0]);
                    } else {
                        return new Function(body[0]);
                    }
                } else {
                    return null;
                }
            } else {
                return eval(funcString);
            }
        }

        function cloneOtherType(targe, type) {
            const Ctor = targe.constructor;
            let typeObj = {
                boolTag: '',
                numberTag: '',
                stringTag: '',
                errorTag: '',
                dateTag: new Ctor(targe),
                regexpTag: cloneReg(targe),
                symbolTag: cloneSymbol(targe),
                funcTag: cloneFunction(targe)
            }
            return typeObj[type] || null
        }
            // 克隆原始类型
            if (!isObject(target)) {
                return target;
            }

            // 初始化
            const type = getType(target);
            let cloneTarget;
            if (deepTag.includes(type)) {
                cloneTarget = getInit(target);
            } else {
                return cloneOtherType(target, type);
            }

            // 防止循环引用
            if (map.get(target)) {
                return map.get(target);
            }
            map.set(target, cloneTarget);

            // 克隆set
            if (type === setTag) {
                target.forEach(value => {
                    cloneTarget.add(deepClone(value, map));
                });
                return cloneTarget;
            }

            // 克隆map
            if (type === mapTag) {
                target.forEach((value, key) => {
                    cloneTarget.set(key, deepClone(value, map));
                });
                return cloneTarget;
            }

            // 克隆对象和数组
            const keys = type === arrayTag ? undefined : Object.keys(target);
            forEach(keys || target, (value, key) => {
                if (keys) {
                    key = value;
                }
                cloneTarget[key] = deepClone(target[key], map);
            });
            return cloneTarget;
    }

# 相对好用的时间格式转换

/**
* oldDate: Date | String | Number
* fmt: yyyy-MM-dd hh:mm
*/
const formatDate = (oldDate, fmt) => {
  let date = new Date()
  if (typeof oldDate === 'string' || typeof oldDate === 'number') {
    date = new Date(+oldDate)
  } else {
    date = oldDate
  }
if (/(y+)/.test(fmt)) {
  fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))  }
  let o = {
  'M+': date.getMonth() + 1,
  'd+': date.getDate(),
  'h+': date.getHours(),
  'm+': date.getMinutes(),
  's+': date.getSeconds()  }
  function padLeftZero (str) {
    return ('00' + str).substr(str.length)
  }
  for (let k in o) {
    if (new RegExp(`(${k})`).test(fmt)) {
      let str = o[k] + ''
      fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str))
    }
  }
  return fmt
}
// yyyy年MM月dd -> 2019年09月10日
// hh分mm秒 -> 16分14秒

# 获取指定天的时间戳

/**
* num: number, 正数为未来时间,负数为过去时间
*
*/
const setDate = (num) => {  return Date.now() + num * 24 * 60 * 60 * 1000}
// 12 个小时之前的时间 -> setDate(-.5)  = 1568060635065
// 24 个小时之前的时间 -> setDate(-1) = 1568017465917
// 三天后的时间 -> setDate(3) = 1568363086637

# js设置Cookie

const setCookie = (name, value, Hours) => {
    let d = new Date();
    let offset = 8;
    let utc = d.getTime() + (d.getTimezoneOffset() * 60000);
    let nd = utc + (3600000 * offset);
    let exp = new Date(nd);
    exp.setTime(exp.getTime() + Hours * 60 * 60 * 1000);
    document.cookie = name + "=" + escape(value) + ";path=/;expires=" + exp.toGMTString()
}

# js获取Cookie

const getCookie = (name) => {
  let arr = document.cookie.match(new RegExp("(^| )" + name + "=([^;]*)(;|$)"));
  if (arr != null) return unescape(arr[2]);
  return null
}

# js 加入收藏夹

const AddFavorite = (sURL, sTitle) => {
    try {
        window.external.addFavorite(sURL, sTitle)
    } catch(e) {
        try {
            window.sidebar.addPanel(sTitle, sURL, "")
        } catch(e) {
            alert("加入收藏失败,请使用Ctrl+D进行添加")
        }
    }
}

# js 压缩css代码

const miniCss = (s) => {
    s = s.replace(/\/\*(.|\n)*?\*\//g, ""); //删除注释
    s = s.replace(/\s*([\{\}\:\;\,])\s*/g, "$1");
    s = s.replace(/\,[\s\.\#\d]*\{/g, "{"); //容错处理
    s = s.replace(/;\s*;/g, ";"); //清除连续分号
    s = s.match(/^\s*(\S+(\s+\S+)*)\s*$/); //去掉首尾空白
    return (s == null) ? "" : s[1];
}

# localStorage 储存一段时间后失效

/**
 * localStorage 存贮某一段时间失效
 * @param {String} key  属性
 * @param {*} value 存贮值
 * @param {String} expire 过期时间,毫秒数
 */
export const localStorageSetExpire = (key, value, expire) => {
  if (typeof (value) === 'object') value = JSON.stringify(value)
  localStorage.setItem(key, value)
  setTimeout(() => {
    localStorage.removeItem(key)
  }, expire)
}

# 去掉左右空格

/**
 * 去掉字符左右空格
 * @param {String} str 字符
 */
export const strTrimLeftOrRight = str => {
  return str.replace(/(^\s*)|(\s*$)/g, "")
}

最近更新: 12/5/2019, 9:02:53 PM