JavaScript处理数组、对象和正则的实用函数

前言

这次就来分享一下最近项目中遇到的一些javascript的业务逻辑函数,将要介绍的这些函数可以提成一个公用的工具函数以便于在以后的项目中进行使用,希望你看过之后对你有所帮助。

1、数组相关

数组是我们在写业务逻辑中经常需要处理的对象,但是这次我就只把最近遇到的,项目中相对频繁出现的业务处理函数进行总结记录,至于其他你觉得有用的可以自行补充记录。

1.1 数组拆分为多个数组

该需求是在处理请求时,需要将数据分批进行请求,所以需要我们将一个大数组数据采用下面的方法进行截取重组。如下:

php 复制代码
/**
 * 把一个数组拆分成几个数组
 * @param array  需要拆分的数组
 * @param size 每组数组多少个,如:10
 */
export function splitArray(array, size) {
  let data = [];
  for (let i = 0; i < array.length; i += size) {
      data.push(array.slice(i, i + size));
  }
  return data;
}

在函数内部,先创建了一个空数组data用于存储分割后的子数组,使用for循环遍历原始数组array;循环迭代时,以size为步长,每次取出size大小的元素;利用array.slice(start, end)方法截取array中的子数组,并将其推送到data中。最终返回包含分割后的子数组的data数组。

1.2 判断数组相等

javascript 复制代码
方法一:
/** 
 * 数组内元素一样(顺序可不一样)
 * @param arr1
 * @param arr2
 */
export function isArrEqual (arr1, arr2) {
    return arr1.length === arr2.length && arr1.every((ele) => arr2.includes(ele));
};

方法二:
/** 
 * 数组内元素一样(顺序一样)
 * @param arr1
 * @param arr2
 */
export function isArrEqual (arr1, arr2) {
    return JSON.stringify(arr1) === JSON.stringify(arr2);
};

判断数组相等提供了上述两种方法:第一种是不管数组内部的元素顺序是否一致,只要数组内的元素都存在即可;而第二种则是通过将数组转为字符串来进行对比,但是有弊端,那就是会忽略数组中的一些特殊类型或特殊值,例如 undefined、函数、或包含循环引用的对象等。

那下面再来写一个更优的方法,如下:

javascript 复制代码
export isArrEqual(arr1, arr2) {
    if (arr1.length !== arr2.length) {
        return false;
    }

    for (let i = 0; i < arr1.length; i++) {
        if (arr1[i] !== arr2[i]) {
            return false;
        }
    }
    return true;
}

这个函数会逐一比较两个数组中的元素。它首先检查两个数组的长度,如果它们长度不同,直接返回 false。然后对比两个数组中每个索引处的元素,如果有任何一个元素不相等,立即返回 false。只有当所有元素都完全相等时,才返回 true

1.3 数组内元素移动位置

该需求是在处理数据时,需要将数组中的某个元素移动到指定位置。如下:

php 复制代码
/** 
 * 数组内元素移动位置
 * @param array
 * @param keyToMove
 * @param newPosition
 */
export function moveElementToPosition(array, keyToMove, newPosition) {
    const indexToMove = array.findIndex(element => element.label == keyToMove);
    if (indexToMove != -1) {
        const elementToMove = array.splice(indexToMove, 1)[0]; // 移除要移动的元素
        array.splice(newPosition, 0, elementToMove); // 插入到新位置
    }
    return array
}

这段代码使用array.findIndex()方法查找数组中满足指定条件的第一个元素,并返回其索引。如果找到了该元素,则使用array.splice(indexToMove, 1)[0]从数组中删除找到的元素,并将其存储在elementToMove变量中。 array.splice(newPosition, 0, elementToMove)将刚刚移除的元素elementToMove插入到数组的新位置 newPosition。最后,函数返回操作后的数组。

1.4 对象转为数组

该需求其实是上述数组内元素移动位置的前提,因为对象是无序的,所以需要将其先转为数组,然后对数组进行移位操作,所以将对象转为数组的方法如下:

php 复制代码
/** 
 * 对象转为数组
 * @param obj
 */
export function obj2Arr(obj) {
    const resultArray = [];
    for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
            resultArray.push({ label: key, value: obj[key] });
        }
    }
    return resultArray;
}

这段代码定义了一个函数obj2Arr,其功能是将给定的对象转换为数组。这个数组包含了对象中每个键值对,每个键值对会以对象的形式存储在数组中,其中label对应对象的键,value对应对象的键对应的值。

2、对象相关

对象也是javascript中经常需要处理的数据类型,下面我也总结了最近用到的一些处理对象的方法,如下:

2.1 数组转对象

javascript 复制代码
/** 
 * 数组转对象
 * @param arr
 */
export function arr2Obj(arr) {
    return arr.reduce((acc, item) => {
        acc[item.key] = item.value;
        return acc;
    }, {});
}

这段代码定义了一个函数arr2Obj,其作用是将一个由对象组成的数组转换为一个对象。这个数组中的每个对象都有 keyvalue属性,函数通过使用reduce方法,将这些对象的key属性作为新对象的键,value属性作为新对象的对应值,最终返回一个包含了数组中所有对象键值对的对象。

2.2 对象转为Map

javascript 复制代码
/**
 * 对象转为 Map
 * @param obj
 * @returns
 */
export function objToStrkeyMap(obj) {
    let strMap = new Map();
    for (let k of Object.keys(obj)) {
        strMap.set(k, obj[k]);
    }
    return strMap;
}

这段代码定义了一个函数objToStrkeyMap,其作用是将一个对象转换为一个Map数据结构,其中对象的键会成为 Map的键,对应的值会成为Map的值。

2.3 JSON转为Map

这里需要用到上面对象转为Map的方法,如下:

javascript 复制代码
/**
 * JSON 转为 Map,所有键名都是字符串
 * @param jsonStr
 * @returns
 */
export function jsonToStrkeyMap(jsonStr) {
    return objToStrkeyMap(JSON.parse(jsonStr));
}

2.4 克隆对象

当在对对象进行修改时,需要先对其进行备份,以便在修改后对比或恢复至原始状态时,克隆对象就很有用,这里就给出最简的方法,如下:

javascript 复制代码
/**
* 克隆对象
* @param obj
* @returns {any}
*/
export function objClone(obj) {
    return JSON.parse(JSON.stringify(obj));
}

使用JSON.stringify(obj)将对象转换为JSON字符串,然后 JSON.parse()将这个JSON字符串再转换回对象,从而创建了对象的深层拷贝,返回了一个全新的对象副本。

那肯定会有人来杠,这种方法有啥有啥弊端,我都知道。最终就会扯到写一个深拷贝才罢休,如下:

javascript 复制代码
export function deepClone(obj, hash = new WeakMap()) {
    let isComplexDataType = (obj) => {
        return (typeof obj === "object" || typeof obj === "function") && obj !== null;
    };

    if (obj.constructor === Date) return new Date(obj); //日期对象直接返回一个新的日期对象
    if (obj.constructor === RegExp) return new RegExp(obj); //正则对象直接返回一个新的正则对象
    //如果循环引用了就用weakMap来解决
    if (hash.has(obj)) return hash.get(obj);
    let allDesc = Object.getOwnPropertyDescriptors(obj);
    //遍历传入参数所有键的特性
    let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc);
    //继承原型链
    hash.set(obj, cloneObj);
    for (let key of Reflect.ownKeys(obj)) {
        cloneObj[key] =
            isComplexDataType(obj[key]) && typeof obj[key] !== "function"
                ? this.deepClone(obj[key], hash)
                : obj[key];
    }
    return cloneObj;
}

3、正则相关

下面就来把我使用的一些正则验证房分享一下,如果有需要就拷贝吧,没需要的当个乐子看看就好。

3.1 校验手机号

javascript 复制代码
/**
* 校验手机号是否符合规则
* @param phone
*/
export function verifyPhone (phone: string) {
    return /^1[3|4|5|6|7|8|9][0-9]\d{8}$/.test(phone);
}

3.2 校验只能输入中文

javascript 复制代码
/**
* 校验只能输入中文
* @param str
* @returns
*/
export function verifyChinese (str: string) {
    return /^[\u4e00-\u9fa5]+$/.test(str)
}

3.3 校验只能输入中英文数字

javascript 复制代码
/**
* 校验只能输入中英文数字
* @param str
*/
export function verifyChineseAndEnglish(str) {
    return /^[A-Za-z0-9\u4E00-\u9FFF]+$/.test(str)
}

3.4 检验只能输入英文

javascript 复制代码
/**
* 校验只能输入英文
* @param str
*/
export function verifyEnglish (str) {
    return /^[a-zA-Z]+$/.test(str)
}

3.5 校验不能输入特殊字符

javascript 复制代码
/**
* 校验不能输入特殊字符
* @param str
*/
export function verifySpecialChar (str) {
    return /[!`~,.<>;':"/[\]|{}()=_+-]/.test(str)
}

3.6 过滤emoji表情

scss 复制代码
/**
* 过滤 emoji 表情
* @param str
*/
export function filterEmoji(str) {
    return str.replace(/(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|\ud83c[\ude32-\ude3a]|\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])/g, "*");
}

3.7 校验身份证

javascript 复制代码
/**
* 校验身份证号是否符合规则
* @param phone
* @returns
*/
export function verifyIDCard (idCard) {
    const cities = {
        11: "北京", 12: "天津", 13: "河北", 14: "山西", 15: "内蒙古",
        21: "辽宁", 22: "吉林", 23: "黑龙江", 31: "上海", 32: "江苏",
        33: "浙江", 34: "安徽", 35: "福建", 36: "江西", 37: "山东", 41: "河南",
        42: "湖北", 43: "湖南", 44: "广东", 45: "广西", 46: "海南", 50: "重庆",
        51: "四川", 52: "贵州", 53: "云南", 54: "西藏", 61: "陕西", 62: "甘肃",
        63: "青海", 64: "宁夏", 65: "新疆", 71: "台湾", 81: "香港", 82: "澳门", 91: "国外"
    };
    // 正则先过滤
    const reg = /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
    if (!reg.test(idCard)) {
        return false;
    };
    // 然后再检查省份
    const provinceCode = idCard.substring(0, 2);
    if (cities[provinceCode] === undefined) {
        return false;
    }
    // 最后验证校验码
    return checkCode(idCard);
}

/**
* 身份证号校验位的检测
* @param idCard
* @returns
*/
function checkCode (idCard) {
    // 将前17位加权因子保存在数组里
    const factor = [ 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 ];
    // 这是除以11后,可能产生的11位余数、验证码,也保存成数组
    const parity = [ 1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2 ]; 
    const code = idCard.substring(17); // 得到最后一位身份证号码
    let sum = 0; // 用来保存前17位各自乖以加权因子后的总和
    for (let i = 0; i < 17; i++) {
        sum += Number(idCard[i]) * factor[i];
    }
    // 如果校验码所在数组的位置的值和parity中的值相等,则验证正确,否则无效
    if (parity[sum % 11] == code.toUpperCase()) {
        return true;
    }
    return false;
}

4、其他

我最近开发中经常遇到的其他方法有下面几个,还有一些没有那么频繁就没有必要赘述了。

4.1 比较版本号

ini 复制代码
/**
* 比较版本号
*/
export function compareVersionNumbers(version1, version2) {
    const v1 = version1.split('.');
    const v2 = version2.split('.');
   
    const maxLength = Math.max(v1.length, v2.length);
   
    for (let i = 0; i < maxLength; i++) {
        const num1 = parseInt(v1[i] || 0);
        const num2 = parseInt(v2[i] || 0);
   
        if (num1 > num2) {
            return 1;
        } else if (num1 < num2) {
            return -1;
        }
    }
   
    return 0;
}

这个函数compareVersionNumbers接受两个版本号字符串version1version2作为参数。它会按照版本号的常规格式(X.Y.Z),将版本号字符串分割为数字数组,然后逐个比较对应位置的数字,以确定两个版本号的大小关系。如果版本号version1大于version2,则返回1;如果版本号version1小于version2,则返回 -1;如果版本号相等,则返回0

4.2 延时

项目中经常需要我们写一个延时来执行一些渲染,这个时候最好还希望是同步的,所以就有了下面这个方法,特别好用。如下:

javascript 复制代码
/**
* 延时
* @param value
*/
export function sleep (value) {
    return new Promise(resolve => {
        const timeout = setTimeout(() => resolve(timeout), value)
    })
}

4.3 截取字符串

截取字符串也是经常会遇到的,所以干脆写一个函数来进行引用,如下:

matlab 复制代码
/**
* 截取字符串并加身略号
* @param str 要截取的字符串
* @param length
*/
export function subText(str, length) {
    if (str.length == 0) {
        return '';
    }
    if (str.length > length) {
        return str.substr(0, length) + '...';
    } else {
        return str;
    }
}

这个函数subText用于截取字符串,并在超出指定长度时添加省略号。如果输入字符串为空,它返回一个空字符串。如果输入字符串长度大于指定长度,则它截取字符串并添加省略号,否则返回原字符串。

总结

上述就是最近开发中遇到的一些javascript处理数据的方法,这里做个整理并记录也是方便后续自己进行查看,如果有需要的就采纳借鉴一下,文中的一些方法当然也有更优的解,你可以在评论区进行指正和优化。最后希望这篇文章对你能有所帮助!

后语

小伙伴们,如果觉得本文对你有些许帮助,点个👍或者➕个关注再走吧^_^ 。另外如果本文章有问题或有不理解的部分,欢迎大家在评论区评论指出,我们一起讨论共勉。

相关推荐
也无晴也无风雨1 小时前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
Martin -Tang2 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
FakeOccupational3 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
放逐者-保持本心,方可放逐4 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄5 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
阮少年、5 小时前
java后台生成模拟聊天截图并返回给前端
java·开发语言·前端
郝晨妤6 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙
AvatarGiser7 小时前
《ElementPlus 与 ElementUI 差异集合》Icon 图标 More 差异说明
前端·vue.js·elementui
喝旺仔la7 小时前
vue的样式知识点
前端·javascript·vue.js
别忘了微笑_cuicui7 小时前
elementUI中2个日期组件实现开始时间、结束时间(禁用日期面板、控制开始时间不能超过结束时间的时分秒)实现方案
前端·javascript·elementui