你可能忽略的10種JavaScript快樂寫法
你可能忽略的10種JavaScript快樂寫法
前言
- 程式碼的簡潔、美感、可讀性等等也許不影響程式的執行,但是卻對人(開發者)的影響非常之大,甚至可以說是影響開發者幸福感的重要因素之一;
- 瞭解一些有美感的程式碼,不僅可以在一定程度上提高程式設計師們的開發效率,有些還能提高程式碼的效能,可謂是一舉多得;
筆者至今難以忘記最開始踏入程式設計師領域時接觸的一段List
內嵌for
的Python程式碼:
python
array = [[16, 3, 7], [2, 24, 9], [4, 1, 12]]
row_min = [min(row) for row in array ]
print(row_min)
這可能就是動態語言非常優秀的一點,而JavaScript同樣作為動態語言,其中包含的優秀程式碼片段也非常之多,比如我們通過JavaScript也可以非常輕鬆地實現上述的功能:
JavaScript
const array = [[16, 3, 7], [2, 24, 9], [4, 1, 12]]
const row_min = array.map(item => Math.min(...item))
console.log(row_min)
能寫出優秀的程式碼一直是筆者所追求的,以下為筆者在開發閱讀過程積累的一些程式碼片段以及收集了網際網路上一些優秀程式碼片段,希望對你有所幫助
概述
這裡,考慮到有些技巧是大家見過的或者說是已經爛熟於心的,但總歸有可能有些技巧沒有留意過,為了讓大家更加清楚的找到自己想要查閱的內容以查漏補缺,所以這裡筆者貼心地為大家提供了一張本文內容的索引表,供大家翻閱以快速定位,如下:
|應用場景標題|描述|補充1|補充2|
|-|-|-|-|
|陣列去重|略|通過內建資料解構特性進行去重[] => set => []
|通過遍歷並判斷是否存在進行去重[many items].forEach(item => (item <不存在於> uniqueArr) && uniqueArr.push(item))
|
|陣列的最後一個元素|獲取陣列中位置最後的一個元素|使用at(-1)
|略|
|陣列物件的相關轉換|略|物件到陣列:Object.entries()
|陣列到物件:Obecjt.fromEntries()
|
|短路操作|通過短路操作避免後續表示式的執行|a或b
:a真b不執行|a且b
:a假b不執行|
|基於預設值的物件賦值|通過物件解構合併進行帶有預設值的物件賦值操作|{...defaultData, ...data}
|略|
|多重條件判斷優化|單個值與多個值進行對比判斷時,使用includes
進行優化|[404,400,403].includes
|略|
|交換兩個值|通過物件解構操作進行簡潔的雙值交換|[a, b] = [b, a]|略|
|位運算|通過位運算提高效能和簡潔程度|略|略|
|replace()
的回撥|通過傳入回撥進行更加細粒度的操作|略|略|
|sort()
的回撥|通過傳入回撥進行更加細粒度的操作|根據字母順序排序|根據真假值進行排序|
陣列去重
這不僅是我們平常編寫程式碼時經常會遇到的一個功能實現之一,也是許多面試官在考查JavaScript基礎時喜歡考查的題目,比較常見的基本有如下兩類方法:
1)通過內建資料結構自身特性進行去重
主要就是利用JavaScript內建的一些資料結構帶有不包含重複值的特性,然後通過兩次資料結構轉換的消耗[] => set => []
從而達到去重的效果,如下演示:
js
const arr = ['justin1go', 'justin2go', 'justin2go', 'justin3go', 'justin3go', 'justin3go'];
const uniqueArr = Array.from(new Set(arr));
// const uniqueArr = [...new Set(arr)];
2)通過遍歷並判斷是否存在進行去重
白話描述就是:通過遍歷每一項元素加入新陣列,新陣列存在相同的元素則放棄加入,虛擬碼:[many items].forEach(item => (item <不存在於> uniqueArr) && uniqueArr.push(item))
至於上述的<不存在於>
操作,可以是各種各樣的方法,比如再開一個for
迴圈判斷新陣列是否有相等的,或者說利用一些陣列方法判斷,如indexOf、includes、filter、reduce等等
js
const arr = ['justin1go', 'justin2go', 'justin2go', 'justin3go', 'justin3go', 'justin3go'];
const uniqueArr = [];
arr.forEach(item => {
// 或者!uniqueArr.includes(item)
if(uniqueArr.indexOf(item) === -1){
uniqueArr.push(item)
}
})
結合filter()
,判斷正在遍歷的項的index,是否是原始陣列的第一個索引:
js
const arr = ['justin1go', 'justin2go', 'justin2go', 'justin3go', 'justin3go', 'justin3go'];
const uniqueArr = arr.filter((item, index) => {
return arr.indexOf(item, 0) === index;
})
結合reduce()
,prev初始設為[]
,然後依次判斷cur
是否存在於prev
陣列,如果存在則加入,不存在則不動:
js
const arr = ['justin1go', 'justin2go', 'justin2go', 'justin3go', 'justin3go', 'justin3go'];
const uniqueArr = arr.reduce((prev,cur) => prev.includes(cur) ? prev : [...prev,cur],[]);
陣列的最後一個元素
對於獲取陣列的最後一個元素,可能平常見得多的就是arr[arr.length - 1]
,我們其實可以使用at()
方法進行獲取
js
const arr = ['justin1go', 'justin2go', 'justin3go'];
console.log(arr.at(-1)) // 倒數第一個值
console.log(arr.at(-2)) // 倒數第二個值
console.log(arr.at(0)) // 正數第一個
console.log(arr.at(1)) // 正數第二個
注:node14應該是不支援的,目前筆者並不建議使用該方法,但獲取陣列最後一個元素是很常用的,就應該像上述語法一樣簡單...
陣列物件的相互轉換
- 相信大家比較熟悉的是從物件轉換為陣列的幾種方法如:
Object.keys()
、Object.values()
、Object.entries
; - 但其實還可以通過
Object.fromEntries()
將一個特定陣列轉換回物件:
```js const entryified = [ ["key1", "justin1go"], ["key2", "justin2go"], ["key3", "justin3go"] ];
const originalObject = Object.fromEntries(entryified);
console.log(originalObject);
```
短路操作
被合理運用的短路操作不僅非常的優雅,還能減少不必要的計算操作
1)基本介紹
主要就是||
或操作、&&
且操作當第一個條件(左邊那個)已經能完全決定整個表示式的值的時候,編譯器就會跳過該表示式後續的計算
- 或操作
a || b
:該操作只要有一個條件為真值時,整個表示式就為真;即a
為真時,b
不執行; - 且操作
a && b
:該操作只要有一個條件為假值時,整個表示式就為假;即a
為假時,b
不執行;
2)例項
網路傳輸一直是前端的效能瓶頸,所以我們在做一些判斷的時候,可以通過短路操作減少請求次數:
js
const nextStep = isSkip || await getSecendCondition();
if(nextStep) {
openModal();
}
還有一個經典的程式碼片段:
js
function fn(callback) {
// some logic
callback && callback()
}
基於預設值的物件賦值
- 很多時候,我們在封裝一些函式或者類時,會有一些配置引數。
- 但這些配置引數通常來說會給出一個預設值,而這些配置引數使用者是可以自定義的
- 除此之外,還有許許多多的場景會用到的這個功能:基於預設值的物件賦值。
```js function fn(setupData) { const defaultSetup = { email: "[email protected]", userId: "justin3go", skill: "code", work: "student" } return { ...defaultSetup, ...setupData } }
const testSetData = { skill: "sing" } console.log(fn(testSetData)) ```
如上{ ...defaultSetup, ...setupData }
就是後續的值會覆蓋前面key
值相同的值。
多重條件判斷優化
js
if(condtion === "justin1go" || condition === "justin2go" || condition === "justin3go"){
// some logic
}
如上,當我們對同一個值需要對比不同值的時候,我們完全可以使用如下的編碼方式簡化寫法並降低耦合性:
js
const someConditions = ["justin1go", "justin2go", "justin3go"];
if(someConditions.includes(condition)) {
// some logic
}
交換兩個值
一般來說,我們可以增加一個臨時變數來達到交換值的操作,在Python中是可以直接交換值的:
python
a = 1
b = 2
a, b = b, a
而在JS中,也可以通過解構操作交換值;
JS
let a = 1;
let b = 2;
[a, b] = [b, a]
簡單理解一下:
- 這裡相當於使用了一個數組物件同時儲存了a和b,該陣列物件作為了臨時變數
- 之後再將該陣列物件通過解構操作賦值給a和b變數即可
同時,還有種比較常見的操作就是交換陣列中兩個位置的值:
js
const arr = ["justin1go", "justin2go", "justin3go"];
[arr[0], arr[2]] = [arr[2], arr[0]]
位運算
關於位運算網上的討論參差不齊,有人說位運算效能好,簡潔;也有人說位運算太過晦澀難懂,不夠易讀,這裡筆者不發表意見,僅僅想說的是儘量在使用位運算程式碼的時候寫好註釋!
下面為一些常見的位運算操作,參考連結
1 ) 使用&運算子判斷一個數的奇偶
js
// 偶數 & 1 = 0
// 奇數 & 1 = 1
console.log(2 & 1) // 0
console.log(3 & 1) // 1
2 ) 使用~, >>, <<, >>>, |
來取整
js
console.log(~~ 6.83) // 6
console.log(6.83 >> 0) // 6
console.log(6.83 << 0) // 6
console.log(6.83 | 0) // 6
// >>>不可對負數取整
console.log(6.83 >>> 0) // 6
3 ) 使用^
來完成值交換
js
var a = 5
var b = 8
a ^= b
b ^= a
a ^= b
console.log(a) // 8
console.log(b) // 5
4 ) 使用&, >>, |
來完成rgb值和16進位制顏色值之間的轉換
``js
/**
* 16進位制顏色值轉RGB
* @param {String} hex 16進位制顏色字串
* @return {String} RGB顏色字串
*/
function hexToRGB(hex) {
var hexx = hex.replace('#', '0x')
var r = hexx >> 16
var g = hexx >> 8 & 0xff
var b = hexx & 0xff
return
rgb(${r}, ${g}, ${b})`
}
/* * RGB顏色轉16進位制顏色 * @param {String} rgb RGB進位制顏色字串 * @return {String} 16進位制顏色字串 / function RGBToHex(rgb) { var rgbArr = rgb.split(/[^\d]+/) var color = rgbArr[1]<<16 | rgbArr[2]<<8 | rgbArr[3] return '#'+ color.toString(16) } // ------------------------------------------------- hexToRGB('#ffffff') // 'rgb(255,255,255)' RGBToHex('rgb(255,255,255)') // '#ffffff' ```
replace()
的回撥函式
之前寫過一篇文章介紹了它,這裡就不重複介紹了,F=>傳送
sort()
的回撥函式
sort()
通過回撥函式返回的正負情況來定義排序規則,由此,對於一些不同型別的陣列,我們可以自定義一些排序規則以達到我們的目的:
- 數字升序:
arr.sort((a,b)=>a-b)
- 按字母順序對字串陣列進行排序:
arr.sort((a, b) => a.localeCompare(b))
- 根據真假值進行排序:
```js const users = [ { "name": "john", "subscribed": false }, { "name": "jane", "subscribed": true }, { "name": "jean", "subscribed": false }, { "name": "george", "subscribed": true }, { "name": "jelly", "subscribed": true }, { "name": "john", "subscribed": false } ];
const subscribedUsersFirst = users.sort((a, b) => Number(b.subscribed) - Number(a.subscribed)) ```
最後
- 個人能力有限,並且程式碼片段這類東西每個人的看法很難保持一致,不同開發者有不同的程式碼風格,這裡僅僅整理了一些筆者自認為還不錯的程式碼片段;
- 可能網際網路上還存在著許許多多的優秀程式碼片段,筆者也不可能全部知道;
- 所以,如果你有一些該文章中沒有包含的優秀程式碼片段,就不要藏著掖著了,分享出來吧~
同時,如本文有所錯誤,望不吝賜教,友善指出🤝
Happy Coding!🎉🎉🎉