天天看點

6 種 JavaScript 技術幫助您編寫更簡潔的代碼

6 種 JavaScript 技術幫助您編寫更簡潔的代碼

英文 | https://betterprogramming.pub/6-javascript-techniques-to-help-you-write-cleaner-code-a5f867a6c750

翻譯 | 楊小愛

JavaScript 靈活而強大。但是,有時可能會很棘手。在 JavaScript 不斷演進并帶來新挑戰的同時,我們在日常工作中也反複遇到類似的問題。

在本文中,我們将分享6個可以幫助您編寫幹淨且可維護的 JavaScript 代碼的小技巧。

現在,我們就開始吧。

1、同時或順序執行多個異步Promise

JavaScript 預設是同步的。為了處理異步代碼,一種常見的方法是使用 Promise。與可能導緻回調地獄的回調相比,Promise 提供了一種更好的方法來處理多個異步請求。

同時處理多個承諾

JavaScript 提供了 Promise.all() 方法來處理并發請求。

// simulate async operation
function fetchMockData(name, timeToWait = 2000) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({ name: name });
    }, timeToWait);
  });
}
const allPromises = [fetchMockData('John'), fetchMockData('Peter')];
Promise.all(allPromises)
  .then((results) => {
    const [first, second] = results;
    console.log(first, second);
  })
  .catch((err) => {
    console.log(err);
  });      

順序處理多個承諾

當您需要一個接一個地執行多個異步請求時,可能會有點棘手。您的第一直覺可能是使用 forEach 或 map,但它們沒有按預期工作。承諾不會等到它完成才開始下一個。

不使用第 3 方庫,最好的方法是使用 reduce 方法。

const allPromises = [fetchMockData('John', 4000), fetchMockData('Peter')];


allPromises.reduce(async (p, curr) => {
  await p;
  return curr.then((result) => {
    console.log('result:', result);
    return curr;
  });
}, Promise.resolve());      

在上面的reduce 方法中,我們傳回一個promise,它在每次疊代中解析為另一個promise。結果是一系列承諾,使異步操作一個接一個地執行。

如輸出所示,雖然,我将第一個 Promise 的逾時設定為 4 秒,第二個 Promise 的預設值為 2 秒,但第一個 Promise 在第二個之前先解決。

6 種 JavaScript 技術幫助您編寫更簡潔的代碼

盡管reduce 本身是同步的,但它允許我們将promise 傳回給累加器,這樣可以使解決方案運作良好。

2、使用 console.time 解決性能問題

有時,我們需要調試 JavaScript 函數來分析性能。開箱即用的 console.time 方法可以幫助我們測量執行時間。

控制台對象提供 time() 和 timeEnd() 方法。

首先,我們使用唯一的字元串标簽調用 console.time() 方法,它啟動一個計時器來跟蹤代碼執行的持續時間。

然後,我們運作要測量的函數。

最後,我們使用相同的标簽調用 console.timeEnd() ,持續時間将在浏覽器控制台中列印出來。

如果需要調試成多步驟的代碼,可以啟動多個定時器,用單獨的定時器測量不同的步驟,以獲得更清晰的圖景。

這是一個帶有兩個計時器的示例:

function accumlateNumbers() {
  let output = 0; 
  for (var i = 1; i <= 4000000; i++) {
    output += i;
  }
  return output; 
}


function callAccumlateFunction() {
  const timeLabel = 'Time taken accumlateNumbers';
  console.time(timeLabel);
  const output = accumlateNumbers();
  console.timeEnd(timeLabel);
}


const timeLabel2 = 'Time taken by callAccumlateFunction';
console.time(timeLabel2);
console.log(callAccumlateFunction());
console.timeEnd(timeLabel2);      

輸出是:

Time taken accumlateNumbers: 9.656005859375 ms
Time taken by callAccumlateFunction: 10.19677734375 ms      

請注意,console.time 不适合需要高精度的時間測量。

3、 使用選項對象模式來處理傳遞給函數的多個參數

options 對象模式是為了解決向函數傳遞多個參數的問題。

使用将參數清單傳遞給函數的正常方式,我們需要注意參數的順序。不正确的順序會造成難以檢測的缺陷。

function createUser(lastName, firstName, jobTitle, role){};
// we try to create a admin user
createUser(“John”,”Paul”,"admin", ”Manager”);      

使用選項對象模式,我們隻需要傳遞一個參數,它是一個包含所有參數選項的命名鍵的對象。

function createUser({lastName, firstName, jobTitle, role}){};
const user = {
  firstName: 'John', 
  lastName: 'John', 
  jobTitle:'Manager', 
  role: 'Admin'
};
createUser(user);      

如上面的代碼片段所示,不僅我們不需要擔心參數的順序,而且帶有選項對象模式的命名參數使代碼更易于閱讀。

選項對象模式通常用于四個或更多參數的情況。

4、組合多個函數

函數組合是将多個函數組合在一起,并将每個函數應用于前一個函數的結果的方法。在正确的用例中使用時,函數組合可以使您的代碼簡潔優雅。

這是一個簡單的例子:

const applyFixDiscount= (x) => x - 20
const applyVipOffer = (x) => x / 2
const getDiscountedPrice = (x) => applyVipOffer(applyFixDiscount(x))
console.log(getDiscountedPrice(100)) // 40      

上述方法有效,但當更多功能組合在一起時将難以閱讀。更好的方法是使用下面的 compose 函數。

compose =
  (...fns) =>
  (initialVal) =>
    fns.reduceRight((val, fn) => fn(val), initialVal);


const getDiscountedPrice = compose(applyVipOffer, applyFixDiscount);
console.log('price:', getDiscountedPrice2(100))  // 40      

通用的 compose 函數可以将多個函數作為輸入并一一調用。是以我們稱 compose 為高階函數。高階函數的優勢在于它能夠以非常有表現力的方式組合多個操作。

請注意,它使用了 reduceRight,這意味着函數是從右到左執行的。另一種方法是下面的管道方法。它使用reduce,是以順序是從左到右。

pipe = (...fns) => (initialVal) => fns.reduce((val, fn) => fn(val), initialVal);


const getDiscountedPrice = pipe(applyFixDiscount, applyVipOffer);      

應用函數組合鼓勵開發人員将程式分解為更小的部分,并将動作或行為抽象為函數。它讓你首先考慮輸入和輸出,而不是專注于實作細節。

結果将是更具可讀性、可測試性和可重用性的代碼。

在實際項目中,函數組合的正确用例包括資料處理、複雜規則計算、工作流操作等。

5、使用解構來提取資料

解構是一種将值從對象屬性或數組解包到多個變量的簡單而簡潔的方法。

解構的基本例子是:

const user = {
    name: 'John Paul',
    age: 23
};
// from object properties
const {name, age} = user;
const count= ['one', 'two', 'three'];
// array destructuring
const [first, second, third] = count;      

提供了一些有用的破壞功能,包括預設值、跳過數組元素、配置設定新變量名等。您可以在此處找到完整清單。

下面是一些我經常使用的實際例子。

從函數結果中析構

function getUser() {
  return {name: ‘John’, age: 24};
}
const {name, age} = getUser(); // name='John', age=24      

拆分數組

const [first, ...rest] = ['1', '2', '3', '4'];
// output: first='1', rest=['2', '3', '4']      

擷取數組的第一個元素

const fruits = [‘apple’, ‘orange’, ‘pear’];
[first] = fruits; // first= 'apple'      

銷毀 promise.all() 的結果

Promise.all([ promise1, promise2, promise3])
.then( results =>{    
    const [first, second, third] = results;
})      

6、有效地使用數組

數組是我們大多數人每天處理的最常見的資料結構。以下是對數組操作的一些提示:

使用slice不變地對數組進行排序

我們經常想對一個數組進行排序并得到一個不可變的副本。不幸的是, .sort 會改變原始數組。使用下面的slice,我們可以在不影響原始數組的情況下獲得一個排序數組。

const newArr = arr.slice().sort()      

請注意,slice從原始數組中傳回元素的淺拷貝。如果您需要進行深度克隆,您可能喜歡使用不同的方法。

從數組中删除重複項

有多種方法可以從數組中删除重複項。最簡單也是我最喜歡的方法是使用 Set。

Set 是在 ES6 中引入的,它表示一個唯一值清單。在下面的示例中,我們使用擴充運算符将 Set 操作的結果作為數組傳回。

const arr = [1,2,3,2,3,4,5];
console.log([...new Set(arr)]); // [1,2,3,4,5]      

請注意 Set 方法僅适用于原始值。

從數組中過濾掉虛假值

在 JavaScript 中,假值可以是空字元串、false、0、null、NaN 或 undefined。下面是我最喜歡的從數組中過濾掉虛假值的方法。

const arrToFilter = ["user", "", 0,  NaN, 9, true, undefined, "red", false];
const result = mixedArr.filter(Boolean);
console.log(result); // returns ["user", 9, true, "red"]      

如果您之前沒有使用過它,您可能想知道 filter(Boolean) 是如何工作的?

Boolean 是一個對象包裝器。在 filter(Boolean) 方法中,數組中的每一項都被傳入并評估如下。結果為真或假,假值将被過濾掉。

.filter(x=> Boolean(x));      

使用 Array.every 和 Array.some 來簡化代碼

Array.every 和 Array.some 是簡化代碼的非常友善的方法。與其他方法如 forEach 或 reduce 相比,Array.every 和 Array.some 使代碼更具可讀性和簡潔性。

const users = [
    { name: 'john', role: 'admin' },
    { name: 'peter', role: 'dev' },
    { name: 'mary', role: 'dev' }
  ];
const isAllDeveloperRole = users.every(f => f.role === 'dev');
const hasDeveloperRole = users.some(f => f.role === 'dev');      

總結

我希望這篇文章對您有用。感謝您的閱讀。

6 種 JavaScript 技術幫助您編寫更簡潔的代碼

繼續閱讀