工作中常用函数(JS篇)

生成任意长度随机字符串

/**
* @param {Number} len 
*/
const getRandomStr = (len) => {
    let str = "";
    while(str.length < len) {
        str += Math.random().toString(36).substring(2);
    }
    return str.substring(0, len);
}

利用了Math.random().toString方法可以接收一个基数作为参数,这个基数从2到36封顶。如果不指定,默认基数是10进制。

PS 随机串长度小于10时,建议在获取后做是否存在校验。

const getRandomStr = (len) => {
  let str = "";
  while(str.length < len) {
      str += Math.random().toString(36).substring(2);
  }
  return str.substring(0, len);
}

let lArr = [3, 5, 10, 15] // 随机字符串长度
let rArr = [100, 1000, 10000] // 随机次数
let obj = {}; // 记录随机字符串
// 验证随机字符串重复概率
const testRandom = () => {
  lArr.forEach( len => {
    rArr.forEach( r => {
      let total = r, count = 0;
      while(r--) {
        let rs = getRandomStr(len);
        if(obj[rs]) {
          count++ ;
        } else {
          obj[rs] = true;
        }
      }
      console.log(`随机生成${len}位字符串${total}次,重复${count}个,重复率${Math.round(count/total*10000)/100}%。`);
      obj = {};
    })
  })
}
testRandom();
// 随机生成3位字符串100次,重复0个,重复率0%。
// 随机生成3位字符串1000次,重复10个,重复率1%。
// 随机生成3位字符串10000次,重复971个,重复率9.71%。
// 随机生成5位字符串100次,重复0个,重复率0%。
// 随机生成5位字符串1000次,重复0个,重复率0%。
// 随机生成5位字符串10000次,重复1个,重复率0.01%。
// 随机生成10位字符串100次,重复0个,重复率0%。
// 随机生成10位字符串1000次,重复0个,重复率0%。
// 随机生成10位字符串10000次,重复0个,重复率0%。
// 随机生成15位字符串100次,重复0个,重复率0%。
// 随机生成15位字符串1000次,重复0个,重复率0%。
// 随机生成15位字符串10000次,重复0个,重复率0%。

RGB色值转Hex格式

/**
* RGB色值转Hex格式
* @param {String} color 'rgb(255,23,23)' || 'rgba(255,23,23,0.3)'
*/
const colorRGB2Hex = (color) => {
      let rgb = color.split(',');
      if(rgb.length > 3) {
        // rgba(255,255,255,75)
        // rgba 格式,a(取值范围0-1)
        // 如需要,可特殊处理
      }
      let r = parseInt(rgb[0].split('(')[1]);
      let g = parseInt(rgb[1]);
      let b = parseInt(rgb[2].split(')')[0]);

      let hex = "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
      return hex;
    }

比较俩个对象是否相等

/**
* 深度比较两个对象是否相同
* @param {Object} oldData 
* @param {Object} newData 
*/
const isEquals = (oldData, newData) => {
  // 类型为基本类型时,如果相同,则返回true
  if (oldData === newData) return true;
  if (isObject(oldData) && isObject(newData) && Object.keys(oldData).length === Object.keys(newData).length) {
    // 类型为对象并且元素个数相同
    // 遍历所有对象中所有属性,判断元素是否相同
    for (const key in oldData) {
      if (oldData.hasOwnProperty(key)) {
        if (!isEquals(oldData[key], newData[key]))
          // 对象中具有不相同属性 返回false
          return false;
      }
    }
  } else if (isArray(oldData) && isArray(oldData) && oldData.length === newData.length) {
    // 类型为数组并且数组长度相同
    for (let i = 0, length = oldData.length; i < length; i++) {
      if (!isEquals(oldData[i], newData[i]))
        // 如果数组元素中具有不相同元素,返回false
        return false;
    }
  } else {
    // 其它类型,均返回false
    return false;
  }
  // 走到这里,说明数组或者对象中所有元素都相同,返回true
  return true;
};

dom元素是否可见

/**
 * 判断元素是否可见
 * @param {Object} el
 */
export const checkVisible = (el) => {
    let rect = el.getBoundingClientRect();
    //获取当前浏览器的视口高度,不包括工具栏和滚动条
    //document.documentElement.clientHeight兼容 Internet Explorer 8、7、6、5
    let viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight);
    //bottom top是相对于视口的左上角位置
    //bottom大于0或者top-视口高度小于0可见
    return !(rect.bottom < 0 || rect.top - viewHeight >= 0);
}

字节转换

/**
* parsma {Number} bytes
* params {Boolean} returnArr  某些特殊情况需要数值与单位分开处理
*/
const bytesToSize = (bytes, returnArr) => {
    if (bytes == 0) return returnArr ? ['0', 'B'] : '0B';
    if (bytes > 0 && bytes < 1) return returnArr ? [bytes, 'B'] : bytes + 'B';
    let base = 1024, // or 1024
        sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
        i = Math.floor(Math.log(bytes) / Math.log(base));
    // if (i > 4) i = 4; //此处可设置截取最大单位
    bytes = roundToTwo(bytes / Math.pow(base, i)) //保留小数点后俩位
    return returnArr ? [bytes, sizes[i]] : bytes + sizes[i];
}

保留2位小数

const roundToTwo = (decimal) => {
    return +(Math.round(Number(decimal + "e+2")) + "e-2");
};

判断类型

function getType(obj) {
  return Object.prototype.toString.call(obj).slice(8,-1);
}

getType({}); //'Object'
getType([]); //'Array'
getType("a"); //'String'
getType(1); //'Number'
getType(function () {}); //'Function'
getType(true); //'Boolean'
getType(null); //'Null'
getType(undefined); //'Undefined'
getType(Symbol('1234')); //'Symbol'

少位补零

//ES5方法:
var zeroize = function (value, length) {
  if (!length) { length = 2; }
  value = String(value);
  for (i = 0,zeros = ''; i < (length - value.length); i++) {
    zeros += "0";
  }
  return zeros + value;
};
zeroize(9); //retunrn "09"

//ES6方法:
var zeroize = function (value, length) {
  if (!length) { length = 2; }
  value = String(value);
  return value.padStart(length,'0');
};
zeroize(9); //retunrn "09"

百分比计算

//保留俩位小数
function getPercentage(num,total){
  var num = num&&typeof num == "number"&&num || 0;
  var total = total&&typeof total == "number"&&total || 0;
  return Math.round(num/total*10000)/100 + '%'
}

数字每3位加','

方法众多,转换成数组处理、正则表达式等,此处仅举例一种转换成字符串后处理

function toThoussands(num) {
  var num = (num || 0).toString(),result = '';
  while(num.length > 3) {
    result = ',' + num.slice(-3) + result;
    num = num.slice(0,num.length - 3);
  }
  if(num) {
    result = num + result;
  }
  return result;
}

Date数据格式化

function FormatTimeDate(){
  Date.prototype.Format = function (fmt) { 
    var o = {
      "M+": this.getMonth() + 1, //月份
      "d+": this.getDate(), //日
      "h+": this.getHours(), //小时
      "m+": this.getMinutes(), //分
      "s+": this.getSeconds(), //秒
      "q+": Math.floor((this.getMonth() + 3) / 3), //季度
      "S": this.getMilliseconds() //毫秒
    };
    if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
    for (var k in o)
      if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
    return fmt;
  };
}

数组去重

  • ES6:
[...new Set([1,2,3,1,'a',1,'a'])]
//...是扩展运算符
  • ES5:
[1,2,3,1,'a',1,'a'].filter(function(v,i,array){
  return i === array.indexOf(v);
})
var result = [];
var obj = {};
[1,2,3,1,'a',1,'a'].forEach(function(v){
  if(!obj[typeof v + v + '']){
    obj[typeof v + v + ''] = true;
    result.push(v);
  }
});
return result;

PS.上中使用obj[typeof v + v + ''] ,是因为对象的key值为被转换为字符串,obj[1] == obj['1'],所以用"type + value"来判断去重。

根据条件过滤数组

/**
 * filterArr 过滤数组
 * @param {Array} data [需要过滤的原始数组]
 * @param {Object} filterObj [过滤条件,这里写成key-value键值对]
 * @parsm {String} type [过滤条件之间的关系,&& or ||]
 */

function filterArr(data, filterObj, type) {
    let filters = Object.keys(filterObj);
    return data.filter((item) => {
        let flag = filters.reduce((t, v, i) => {
            if (t === 'first' && i === 0) {
                //第一次执行时
                return item[v].includes(filterObj[v]);
            } else if (type === 'or') {
                //过滤条件之间为||关系,满足一个即可
                return t || item[v].includes(filterObj[v]);
            } else if (type === 'and') {
                //过滤条件之间为&&关系,满足全部
                return t && item[v].includes(filterObj[v]);
            }
        }, 'first'); 
        /**
         * Array.reduce方法,在不传初始值的情况下,length为1是不执行的,大坑!!!
         * Array.reduce方法,接受俩个参数:Array.reduce((pre, cur, index, array)=>{ ...}, [initValue]);
         * pre (上一次调用返回的值,或者是提供的初始值(initValue))
         * cur (数组中当前被处理的元素)
         * index (当前元素在数组中的索引)
         * array (调用reduce的数组)
         * initValue (作为第一次调用的第一个参数)
         * 
         * reduce方法,如果不传initialValue,在数组length为1的时候,JS引擎是不执行的。。。。所以在数据长度不确定的情况下,一定要记得传initialValue
         */

        return flag;
    })
}

根据path删除Obj的Key

var delObjectKey = function(obj, path) {
    try {
        if ((typeof(obj) === 'object' || typeof(obj) === 'array') && path) {
            let pathArray = path.split('.');
            let get_value = function(obj, pathArray) {
                let key = pathArray.shift();
                if (key != 'undefined' && key.length < 5 && parseInt(key)) {
                    key = parseInt(key);
                }
                if (!obj[key]) {
                    return false;
                }
                if (pathArray.length == 0) {
                    return delete obj[key];
                }
                obj = obj[key];
                return get_value(obj, pathArray);
            }
            return get_value(obj, pathArray);
        }
        return false;
    } catch (error) {
        console.log(error);
    }

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容