JavaScript中處理數(shù)組,對(duì)象和正則的實(shí)用函數(shù)
1、數(shù)組相關(guān)
數(shù)組是我們?cè)趯憳I(yè)務(wù)邏輯中經(jīng)常需要處理的對(duì)象,但是這次我就只把最近遇到的,項(xiàng)目中相對(duì)頻繁出現(xiàn)的業(yè)務(wù)處理函數(shù)進(jìn)行總結(jié)記錄,至于其他你覺(jué)得有用的可以自行補(bǔ)充記錄。
1.1 數(shù)組拆分為多個(gè)數(shù)組
該需求是在處理請(qǐng)求時(shí),需要將數(shù)據(jù)分批進(jìn)行請(qǐng)求,所以需要我們將一個(gè)大數(shù)組數(shù)據(jù)采用下面的方法進(jìn)行截取重組。如下:
/** * 把一個(gè)數(shù)組拆分成幾個(gè)數(shù)組 * @param array 需要拆分的數(shù)組 * @param size 每組數(shù)組多少個(gè),如: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; }
在函數(shù)內(nèi)部,先創(chuàng)建了一個(gè)空數(shù)組data
用于存儲(chǔ)分割后的子數(shù)組,使用for
循環(huán)遍歷原始數(shù)組array
;循環(huán)迭代時(shí),以size
為步長(zhǎng),每次取出size
大小的元素;利用array.slice(start, end)
方法截取array
中的子數(shù)組,并將其推送到data
中。最終返回包含分割后的子數(shù)組的data
數(shù)組。
1.2 判斷數(shù)組相等
//方法一: /** * 數(shù)組內(nèi)元素一樣(順序可不一樣) * @param arr1 * @param arr2 */ export function isArrEqual (arr1, arr2) { return arr1.length === arr2.length && arr1.every((ele) => arr2.includes(ele)); }; //方法二: /** * 數(shù)組內(nèi)元素一樣(順序一樣) * @param arr1 * @param arr2 */ export function isArrEqual (arr1, arr2) { return JSON.stringify(arr1) === JSON.stringify(arr2); };
判斷數(shù)組相等提供了上述兩種方法:第一種是不管數(shù)組內(nèi)部的元素順序是否一致,只要數(shù)組內(nèi)的元素都存在即可;而第二種則是通過(guò)將數(shù)組轉(zhuǎn)為字符串來(lái)進(jìn)行對(duì)比,但是有弊端,那就是會(huì)忽略數(shù)組中的一些特殊類型或特殊值,例如 undefined
、函數(shù)、或包含循環(huán)引用的對(duì)象等。
那下面再來(lái)寫一個(gè)更優(yōu)的方法,如下:
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; }
這個(gè)函數(shù)會(huì)逐一比較兩個(gè)數(shù)組中的元素。它首先檢查兩個(gè)數(shù)組的長(zhǎng)度,如果它們長(zhǎng)度不同,直接返回 false
。然后對(duì)比兩個(gè)數(shù)組中每個(gè)索引處的元素,如果有任何一個(gè)元素不相等,立即返回 false
。只有當(dāng)所有元素都完全相等時(shí),才返回 true
。
1.3 數(shù)組內(nèi)元素移動(dòng)位置
該需求是在處理數(shù)據(jù)時(shí),需要將數(shù)組中的某個(gè)元素移動(dòng)到指定位置。如下:
/** * 數(shù)組內(nèi)元素移動(dòng)位置 * @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]; // 移除要移動(dòng)的元素 array.splice(newPosition, 0, elementToMove); // 插入到新位置 } return array }
這段代碼使用array.findIndex()
方法查找數(shù)組中滿足指定條件的第一個(gè)元素,并返回其索引。如果找到了該元素,則使用array.splice(indexToMove, 1)[0]
從數(shù)組中刪除找到的元素,并將其存儲(chǔ)在elementToMove
變量中。 array.splice(newPosition, 0, elementToMove)
將剛剛移除的元素elementToMove
插入到數(shù)組的新位置 newPosition
。最后,函數(shù)返回操作后的數(shù)組。
1.4 對(duì)象轉(zhuǎn)為數(shù)組
該需求其實(shí)是上述數(shù)組內(nèi)元素移動(dòng)位置的前提,因?yàn)閷?duì)象是無(wú)序的,所以需要將其先轉(zhuǎn)為數(shù)組,然后對(duì)數(shù)組進(jìn)行移位操作,所以將對(duì)象轉(zhuǎn)為數(shù)組的方法如下:
/** * 對(duì)象轉(zhuǎn)為數(shù)組 * @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; }
這段代碼定義了一個(gè)函數(shù)obj2Arr
,其功能是將給定的對(duì)象轉(zhuǎn)換為數(shù)組。這個(gè)數(shù)組包含了對(duì)象中每個(gè)鍵值對(duì),每個(gè)鍵值對(duì)會(huì)以對(duì)象的形式存儲(chǔ)在數(shù)組中,其中label
對(duì)應(yīng)對(duì)象的鍵,value
對(duì)應(yīng)對(duì)象的鍵對(duì)應(yīng)的值。
2、對(duì)象相關(guān)
對(duì)象也是javascript
中經(jīng)常需要處理的數(shù)據(jù)類型,下面我也總結(jié)了最近用到的一些處理對(duì)象的方法,如下:
2.1 數(shù)組轉(zhuǎn)對(duì)象
/** * 數(shù)組轉(zhuǎn)對(duì)象 * @param arr */ export function arr2Obj(arr) { return arr.reduce((acc, item) => { acc[item.key] = item.value; return acc; }, {}); }
這段代碼定義了一個(gè)函數(shù)arr2Obj
,其作用是將一個(gè)由對(duì)象組成的數(shù)組轉(zhuǎn)換為一個(gè)對(duì)象。這個(gè)數(shù)組中的每個(gè)對(duì)象都有 key
和value
屬性,函數(shù)通過(guò)使用reduce
方法,將這些對(duì)象的key
屬性作為新對(duì)象的鍵,value
屬性作為新對(duì)象的對(duì)應(yīng)值,最終返回一個(gè)包含了數(shù)組中所有對(duì)象鍵值對(duì)的對(duì)象。
2.2 對(duì)象轉(zhuǎn)為Map
/** * 對(duì)象轉(zhuǎn)為 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; }
這段代碼定義了一個(gè)函數(shù)objToStrkeyMap
,其作用是將一個(gè)對(duì)象轉(zhuǎn)換為一個(gè)Map
數(shù)據(jù)結(jié)構(gòu),其中對(duì)象的鍵會(huì)成為 Map
的鍵,對(duì)應(yīng)的值會(huì)成為Map
的值。
2.3 JSON轉(zhuǎn)為Map
這里需要用到上面對(duì)象轉(zhuǎn)為Map
的方法,如下:
/** * JSON 轉(zhuǎn)為 Map,所有鍵名都是字符串 * @param jsonStr * @returns */ export function jsonToStrkeyMap(jsonStr) { return objToStrkeyMap(JSON.parse(jsonStr)); }
2.4 克隆對(duì)象
當(dāng)在對(duì)對(duì)象進(jìn)行修改時(shí),需要先對(duì)其進(jìn)行備份,以便在修改后對(duì)比或恢復(fù)至原始狀態(tài)時(shí),克隆對(duì)象就很有用,這里就給出最簡(jiǎn)的方法,如下:
/** * 克隆對(duì)象 * @param obj * @returns {any} */ export function objClone(obj) { return JSON.parse(JSON.stringify(obj)); }
使用JSON.stringify(obj)
將對(duì)象轉(zhuǎn)換為JSON
字符串,然后 JSON.parse()
將這個(gè)JSON
字符串再轉(zhuǎn)換回對(duì)象,從而創(chuàng)建了對(duì)象的深層拷貝,返回了一個(gè)全新的對(duì)象副本。
那肯定會(huì)有人來(lái)杠,這種方法有啥有啥弊端,我都知道。最終就會(huì)扯到寫一個(gè)深拷貝才罷休,如下:
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); //日期對(duì)象直接返回一個(gè)新的日期對(duì)象 if (obj.constructor === RegExp) return new RegExp(obj); //正則對(duì)象直接返回一個(gè)新的正則對(duì)象 //如果循環(huán)引用了就用weakMap來(lái)解決 if (hash.has(obj)) return hash.get(obj); let allDesc = Object.getOwnPropertyDescriptors(obj); //遍歷傳入?yún)?shù)所有鍵的特性 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、正則相關(guān)
下面就來(lái)把我使用的一些正則驗(yàn)證房分享一下,如果有需要就拷貝吧,沒(méi)需要的當(dāng)個(gè)樂(lè)子看看就好。
3.1 校驗(yàn)手機(jī)號(hào)
/** * 校驗(yàn)手機(jī)號(hào)是否符合規(guī)則 * @param phone */ export function verifyPhone (phone: string) { return /^1[3|4|5|6|7|8|9][0-9]\d{8}$/.test(phone); }
3.2 校驗(yàn)只能輸入中文
/** * 校驗(yàn)只能輸入中文 * @param str * @returns */ export function verifyChinese (str: string) { return /^[\u4e00-\u9fa5]+$/.test(str) }
3.3 校驗(yàn)只能輸入中英文數(shù)字
/** * 校驗(yàn)只能輸入中英文數(shù)字 * @param str */ export function verifyChineseAndEnglish(str) { return /^[A-Za-z0-9\u4E00-\u9FFF]+$/.test(str) }
3.4 檢驗(yàn)只能輸入英文
/** * 校驗(yàn)只能輸入英文 * @param str */ export function verifyEnglish (str) { return /^[a-zA-Z]+$/.test(str) }
3.5 校驗(yàn)不能輸入特殊字符
/** * 校驗(yàn)不能輸入特殊字符 * @param str */ export function verifySpecialChar (str) { return /[!`~,.<>;':"/[\]|{}()=_+-]/.test(str) }
3.6 過(guò)濾emoji表情
/** * 過(guò)濾 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 校驗(yàn)身份證
/** * 校驗(yàn)身份證號(hào)是否符合規(guī)則 * @param phone * @returns */ export function verifyIDCard (idCard) { const cities = { 11: "北京", 12: "天津", 13: "河北", 14: "山西", 15: "內(nèi)蒙古", 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: "臺(tái)灣", 81: "香港", 82: "澳門", 91: "國(guó)外" }; // 正則先過(guò)濾 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; } // 最后驗(yàn)證校驗(yàn)碼 return checkCode(idCard); } /** * 身份證號(hào)校驗(yàn)位的檢測(cè) * @param idCard * @returns */ function checkCode (idCard) { // 將前17位加權(quán)因子保存在數(shù)組里 const factor = [ 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 ]; // 這是除以11后,可能產(chǎn)生的11位余數(shù)、驗(yàn)證碼,也保存成數(shù)組 const parity = [ 1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2 ]; const code = idCard.substring(17); // 得到最后一位身份證號(hào)碼 let sum = 0; // 用來(lái)保存前17位各自乖以加權(quán)因子后的總和 for (let i = 0; i < 17; i++) { sum += Number(idCard[i]) * factor[i]; } // 如果校驗(yàn)碼所在數(shù)組的位置的值和parity中的值相等,則驗(yàn)證正確,否則無(wú)效 if (parity[sum % 11] == code.toUpperCase()) { return true; } return false; }
4、其他
我最近開發(fā)中經(jīng)常遇到的其他方法有下面幾個(gè),還有一些沒(méi)有那么頻繁就沒(méi)有必要贅述了。
4.1 比較版本號(hào)
/** * 比較版本號(hào) */ 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; }
這個(gè)函數(shù)compareVersionNumbers
接受兩個(gè)版本號(hào)字符串version1
和version2
作為參數(shù)。它會(huì)按照版本號(hào)的常規(guī)格式(X.Y.Z),將版本號(hào)字符串分割為數(shù)字?jǐn)?shù)組,然后逐個(gè)比較對(duì)應(yīng)位置的數(shù)字,以確定兩個(gè)版本號(hào)的大小關(guān)系。如果版本號(hào)version1
大于version2
,則返回1
;如果版本號(hào)version1
小于version2
,則返回 -1
;如果版本號(hào)相等,則返回0
。
4.2 延時(shí)
項(xiàng)目中經(jīng)常需要我們寫一個(gè)延時(shí)來(lái)執(zhí)行一些渲染,這個(gè)時(shí)候最好還希望是同步的,所以就有了下面這個(gè)方法,特別好用。如下:
/** * 延時(shí) * @param value */ export function sleep (value) { return new Promise(resolve => { const timeout = setTimeout(() => resolve(timeout), value) }) }
4.3 截取字符串
截取字符串也是經(jīng)常會(huì)遇到的,所以干脆寫一個(gè)函數(shù)來(lái)進(jìn)行引用,如下:
/** * 截取字符串并加身略號(hào) * @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; } }
這個(gè)函數(shù)subText
用于截取字符串,并在超出指定長(zhǎng)度時(shí)添加省略號(hào)。如果輸入字符串為空,它返回一個(gè)空字符串。如果輸入字符串長(zhǎng)度大于指定長(zhǎng)度,則它截取字符串并添加省略號(hào),否則返回原字符串。
總結(jié)
上述就是最近開發(fā)中遇到的一些javascript
處理數(shù)據(jù)的方法,這里做個(gè)整理并記錄也是方便后續(xù)自己進(jìn)行查看,如果有需要的就采納借鑒一下,文中的一些方法當(dāng)然也有更優(yōu)的解。
以上就是JavaScript中處理數(shù)組,對(duì)象和正則的實(shí)用函數(shù)的詳細(xì)內(nèi)容,更多關(guān)于JavaScript處理數(shù)組對(duì)象和正則的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
layer.open提交子頁(yè)面的form和layedit文本編輯內(nèi)容的方法
今天小編就為大家分享一篇layer.open提交子頁(yè)面的form和layedit文本編輯內(nèi)容的方法,具有好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09Javascript中判斷變量是數(shù)組還是對(duì)象(array還是object)
怎樣判斷一個(gè)JavaScript變量是array還是obiect,或許有很多初學(xué)者對(duì)此不是很清楚吧,下面為大家詳細(xì)解答下,希望對(duì)大家有所幫助2013-08-08js實(shí)現(xiàn)貪吃蛇游戲 canvas繪制地圖
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)貪吃蛇游戲,canvas繪制地圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-09-09javascript單頁(yè)面手勢(shì)滑屏切換原理詳解
這篇文章主要為大家詳細(xì)介紹了javascript單頁(yè)面手勢(shì)滑屏切換原理,感興趣的小伙伴們可以參考一下2016-03-03js css 實(shí)現(xiàn)遮罩層覆蓋其他頁(yè)面元素附圖
實(shí)現(xiàn)遮罩層的方法有很多,但大多都是使用js css來(lái)實(shí)現(xiàn)的,本例也實(shí)現(xiàn)一個(gè),效果還不錯(cuò),喜歡的朋友可以感受下2014-09-09html+css+js實(shí)現(xiàn)canvas跟隨鼠標(biāo)的小圓特效源碼
這篇文章主要介紹了html+css+js實(shí)現(xiàn)canvas跟隨鼠標(biāo)的小圓特效源碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03