英文 | https://medium.com/geekculture/9-neat-javascript-one-liners-for-algorithms-and-more-8dd3b0a0fb6d
翻譯 | 楊小愛
了解一些JavaScript 單行代碼片段可以在開發或面試時為你節省寶貴的時間。以下是我在編碼時,實際開發中,我最喜歡的一些JavaScript的代碼片段。
希望對你有所幫助。現在,我們就開始吧。
01、循環一個清單
循環是一個巧妙的技巧,很多時候在算法中你需要循環一個清單。意思是移動多個空格,如果到達清單末尾,則傳回到第一個索引。
是以,如果清單的長度為 8 個值,但你必須移動 10 個值,則你需要落在第二個索引上。
你可以使用一堆複雜的 if 語句,或者……
const wrap = (arr, steps) => arr[steps % arr.length];
wrap(['a','b','c'], 0) // a
wrap(['a','b','c'], 1) // b
wrap(['a','b','c'], 2) // c
wrap(['a','b','c'], 3) // a
// etc ...
您可以根據步驟以不同的方式實作這一點,但要了解的關鍵是modulo。這是一個友善的小運算符。在檢視此類“溢出”類型問題時請記住它。
02、用它的名字記錄一個變量
這是調試時的一個很好的技巧。多虧了對象速記符号,我們可以預設用名稱登出變量。
const someVar = 1;
console.log({ someVar });
// logs out { someVar: 1 }
如果您放入一堆日志(并且在調試時您完全會這樣做),則可能很難跟蹤哪個是哪個,所有異步、擷取和循環都在四處奔波。不必花時間輸入像 console.log('some var', someVar) 這樣的多個參數,而是在一些大括号中折騰并稱它為一天。
03、對象中的可選屬性
如果您不希望屬性指向 undefined 或 null ,您可以使用一些 if 語句來選擇性地添加屬性:
//...
const obj = {
a: 'whatever',
};
if (b) {
obj.c = 'ok';
}
return obj;
//...
然而,它太冗長了,我一直讨厭它。這可能很清楚,但很笨拙。好吧,由于對象傳播,這已成為過去:
return {
a: 'Whatever',
...(b && { c: 'ok'}),
};
我們可以使用擴充和&&邏輯短路來動态檢查是否通過擴充來添加屬性。當您隻想傳回一個對象而不想建立臨時變量時,這非常有用。
04、在 JavaScript 中睡眠
有幾次我不得不處理一個很糟糕的 API,它很慢,而且在它完成時沒有鈎子可以說。是以,我們隻需要等待一秒鐘以確定它已加載。我們還想使用 promises 而不是 setTimeout 回調,是以使用 sleep 函數是理想的。我們可以簡單地等待一秒鐘,然後繼續前進。不需要回調!
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
這也是如何承諾 setInterval 。
05、交換變量值
在現代 JS 之前,如果你想切換兩個變量的值,你必須引入第三個“臨時”值。現在我們有了數組解構和指派,我們可以在一行中完成:
a = 10;
b = 5;
[a,b] = [b,a];
// a is 5, b is 10
06、四舍五入到最接近的 10、100、1000……
如果您需要将數字粗略計算到不同級别,這在算法中很有用。基本上,您要做的是先除以将小數向上移動。“無用”數字現在是小數,您可以将它們四舍五入。要将數字恢複到所需大小,請将其相乘。被忽略的數字現在變成零。這是處理金錢或類似對數的尺度的巧妙技巧,在某個點之後,小數字可以四舍五入。
const rounder = (val, place) => Math.round(val / place) * place;
rounder(1549, 100); // 1500
rounder(15590, 1000); // 16000
07、使用 Set 删除重複項
我剛剛寫了關于 Sets 的文章,顯然這是它們唯一的用途。如果您有一個數組并且想要删除重複項,則可以使用 Set 來完成。
const val = [...new Set([1,2,1,3,1,4])];
// [ 1, 2, 3, 4 ]
不要忘記将新 Set 散布回正常數組中。注意:處理大量清單時要小心,因為這可能不是性能最高的解決方案。
08、計數字元執行個體
如果您有一個數組(或來自字元串的數組)并且想知道字元出現了多少次,那麼使用 reduce 有一種非常巧妙的方法可以做到這一點。
const charTotals = (arr) => arr.reduce((totals, char) => ({
...totals, [char]: (totals[char] || 0) + 1,
}), {});
charTotals('Hi there!'.split(''));
// { H: 1, i: 1, ' ': 1, t: 1, h: 1, e: 2, r: 1, '!': 1 }
這個可能不是那麼有用,但是我想確定您知道兩種技術:動态對象屬性和對象的隐式傳回。這兩件事都是至關重要的知識,如果您不了解 reduce,請閱讀本文。
09、身份證制造商/櫃台
我想我需要為反應元件動态建立非資料庫臨時 ID,并将經典計數器壓縮到一行中。每次調用該函數時,計數器都會增加,并且沒有其他函數可以改變其内部狀态。它使用閉包、立即調用函數表達式和預設值來保持緊湊。
const counter = ((num = 1) => () => num++)();
counter() // 1
counter() // 2
counter() // 3
還有一個額外提示,即在函數參數中使用預設值以避免需要換行。如果你真的想讓起始數字變得動态,你可以停止讓它成為 IIFE:
const startCounter = (num = 1) => () => num++);
const counter100 = startCounter(100)
counter100() // 100
counter100() // 101
counter100() // 102
總結
你得到了代碼的簡潔,也有可能你失去代碼的可讀性。
最終如何取舍,這取決于您和您的團隊喜歡什麼,在程式設計的世界裡,沒有完美,隻有誰更加符合需求,符合項目進度。是以,請不要刻意追求簡潔,保持代碼的可讀性依然重要。
最後,感謝您的閱讀,祝您編碼愉快。