天天看點

9 個用于算法的簡潔 JavaScript 代碼段

9 個用于算法的簡潔 JavaScript 代碼段

英文 | 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      

總結

你得到了代碼的簡潔,也有可能你失去代碼的可讀性。

最終如何取舍,這取決于您和您的團隊喜歡什麼,在程式設計的世界裡,沒有完美,隻有誰更加符合需求,符合項目進度。是以,請不要刻意追求簡潔,保持代碼的可讀性依然重要。

最後,感謝您的閱讀,祝您編碼愉快。

繼續閱讀