<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          6 種 JavaScript 技術(shù)幫助您編寫(xiě)更簡(jiǎn)潔的代碼

          共 4675字,需瀏覽 10分鐘

           ·

          2021-12-19 01:14

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

          翻譯 | 楊小愛(ài)


          JavaScript 靈活而強(qiáng)大。但是,有時(shí)可能會(huì)很棘手。在 JavaScript 不斷演進(jìn)并帶來(lái)新挑戰(zhàn)的同時(shí),我們?cè)谌粘9ぷ髦幸卜磸?fù)遇到類似的問(wèn)題。
          在本文中,我們將分享6個(gè)可以幫助您編寫(xiě)干凈且可維護(hù)的 JavaScript 代碼的小技巧。
          現(xiàn)在,我們就開(kāi)始吧。
          1、同時(shí)或順序執(zhí)行多個(gè)異步Promise
          JavaScript 默認(rèn)是同步的。為了處理異步代碼,一種常見(jiàn)的方法是使用 Promise。與可能導(dǎo)致回調(diào)地獄的回調(diào)相比,Promise 提供了一種更好的方法來(lái)處理多個(gè)異步請(qǐng)求。
          同時(shí)處理多個(gè)承諾
          JavaScript 提供了 Promise.all() 方法來(lái)處理并發(fā)請(qǐng)求。
          // simulate async operationfunction 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);  });

          順序處理多個(gè)承諾

          當(dāng)您需要一個(gè)接一個(gè)地執(zhí)行多個(gè)異步請(qǐng)求時(shí),可能會(huì)有點(diǎn)棘手。您的第一直覺(jué)可能是使用 forEach 或 map,但它們沒(méi)有按預(yù)期工作。承諾不會(huì)等到它完成才開(kāi)始下一個(gè)。

          不使用第 3 方庫(kù),最好的方法是使用 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 方法中,我們返回一個(gè)promise,它在每次迭代中解析為另一個(gè)promise。結(jié)果是一系列承諾,使異步操作一個(gè)接一個(gè)地執(zhí)行。

          如輸出所示,雖然,我將第一個(gè) Promise 的超時(shí)設(shè)置為 4 秒,第二個(gè) Promise 的默認(rèn)值為 2 秒,但第一個(gè) Promise 在第二個(gè)之前先解決。

          盡管reduce 本身是同步的,但它允許我們將promise 返回給累加器,這樣可以使解決方案運(yùn)行良好。

          2、使用 console.time 解決性能問(wèn)題

          有時(shí),我們需要調(diào)試 JavaScript 函數(shù)來(lái)分析性能。開(kāi)箱即用的 console.time 方法可以幫助我們測(cè)量執(zhí)行時(shí)間。

          控制臺(tái)對(duì)象提供 time() 和 timeEnd() 方法。

          首先,我們使用唯一的字符串標(biāo)簽調(diào)用 console.time() 方法,它啟動(dòng)一個(gè)計(jì)時(shí)器來(lái)跟蹤代碼執(zhí)行的持續(xù)時(shí)間。

          然后,我們運(yùn)行要測(cè)量的函數(shù)。

          最后,我們使用相同的標(biāo)簽調(diào)用 console.timeEnd() ,持續(xù)時(shí)間將在瀏覽器控制臺(tái)中打印出來(lái)。

          如果需要調(diào)試成多步驟的代碼,可以啟動(dòng)多個(gè)定時(shí)器,用單獨(dú)的定時(shí)器測(cè)量不同的步驟,以獲得更清晰的圖景。

          這是一個(gè)帶有兩個(gè)計(jì)時(shí)器的示例:

          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 msTime taken by callAccumlateFunction: 10.19677734375 ms

          請(qǐng)注意,console.time 不適合需要高精度的時(shí)間測(cè)量。

          3、?使用選項(xiàng)對(duì)象模式來(lái)處理傳遞給函數(shù)的多個(gè)參數(shù)

          options 對(duì)象模式是為了解決向函數(shù)傳遞多個(gè)參數(shù)的問(wèn)題。

          使用將參數(shù)列表傳遞給函數(shù)的正常方式,我們需要注意參數(shù)的順序。不正確的順序會(huì)造成難以檢測(cè)的缺陷。

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

          使用選項(xiàng)對(duì)象模式,我們只需要傳遞一個(gè)參數(shù),它是一個(gè)包含所有參數(shù)選項(xiàng)的命名鍵的對(duì)象。

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

          如上面的代碼片段所示,不僅我們不需要擔(dān)心參數(shù)的順序,而且?guī)в羞x項(xiàng)對(duì)象模式的命名參數(shù)使代碼更易于閱讀。

          選項(xiàng)對(duì)象模式通常用于四個(gè)或更多參數(shù)的情況。

          4、組合多個(gè)函數(shù)

          函數(shù)組合是將多個(gè)函數(shù)組合在一起,并將每個(gè)函數(shù)應(yīng)用于前一個(gè)函數(shù)的結(jié)果的方法。在正確的用例中使用時(shí),函數(shù)組合可以使您的代碼簡(jiǎn)潔優(yōu)雅。

          這是一個(gè)簡(jiǎn)單的例子:

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

          上述方法有效,但當(dāng)更多功能組合在一起時(shí)將難以閱讀。更好的方法是使用下面的 compose 函數(shù)。

          compose =  (...fns) =>  (initialVal) =>    fns.reduceRight((val, fn) => fn(val), initialVal);
          const getDiscountedPrice = compose(applyVipOffer, applyFixDiscount);console.log('price:', getDiscountedPrice2(100)) // 40

          通用的 compose 函數(shù)可以將多個(gè)函數(shù)作為輸入并一一調(diào)用。因此我們稱 compose 為高階函數(shù)。高階函數(shù)的優(yōu)勢(shì)在于它能夠以非常有表現(xiàn)力的方式組合多個(gè)操作。

          請(qǐng)注意,它使用了 reduceRight,這意味著函數(shù)是從右到左執(zhí)行的。另一種方法是下面的管道方法。它使用reduce,所以順序是從左到右。

          pipe = (...fns) => (initialVal) => fns.reduce((val, fn) => fn(val), initialVal);
          const getDiscountedPrice = pipe(applyFixDiscount, applyVipOffer);

          應(yīng)用函數(shù)組合鼓勵(lì)開(kāi)發(fā)人員將程序分解為更小的部分,并將動(dòng)作或行為抽象為函數(shù)。它讓你首先考慮輸入和輸出,而不是專注于實(shí)現(xiàn)細(xì)節(jié)。

          結(jié)果將是更具可讀性、可測(cè)試性和可重用性的代碼。

          在實(shí)際項(xiàng)目中,函數(shù)組合的正確用例包括數(shù)據(jù)處理、復(fù)雜規(guī)則計(jì)算、工作流操作等。

          5、使用解構(gòu)來(lái)提取數(shù)據(jù)

          解構(gòu)是一種將值從對(duì)象屬性或數(shù)組解包到多個(gè)變量的簡(jiǎn)單而簡(jiǎn)潔的方法。

          解構(gòu)的基本例子是:

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

          提供了一些有用的破壞功能,包括默認(rèn)值、跳過(guò)數(shù)組元素、分配新變量名等。您可以在此處找到完整列表。

          下面是一些我經(jīng)常使用的實(shí)際例子。

          從函數(shù)結(jié)果中析構(gòu)

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

          拆分?jǐn)?shù)組

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

          獲取數(shù)組的第一個(gè)元素

          const fruits = [‘a(chǎn)pple’, ‘orange’, ‘pear’];[first] = fruits; // first= 'apple'

          銷毀 promise.all() 的結(jié)果

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

          6、有效地使用數(shù)組

          數(shù)組是我們大多數(shù)人每天處理的最常見(jiàn)的數(shù)據(jù)結(jié)構(gòu)。以下是對(duì)數(shù)組操作的一些提示:

          使用slice不變地對(duì)數(shù)組進(jìn)行排序

          我們經(jīng)常想對(duì)一個(gè)數(shù)組進(jìn)行排序并得到一個(gè)不可變的副本。不幸的是, .sort 會(huì)改變?cè)紨?shù)組。使用下面的slice,我們可以在不影響原始數(shù)組的情況下獲得一個(gè)排序數(shù)組。

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

          請(qǐng)注意,slice從原始數(shù)組中返回元素的淺拷貝。如果您需要進(jìn)行深度克隆,您可能喜歡使用不同的方法。

          從數(shù)組中刪除重復(fù)項(xiàng)

          有多種方法可以從數(shù)組中刪除重復(fù)項(xiàng)。最簡(jiǎn)單也是我最喜歡的方法是使用 Set。

          Set 是在 ES6 中引入的,它表示一個(gè)唯一值列表。在下面的示例中,我們使用擴(kuò)展運(yùn)算符將 Set 操作的結(jié)果作為數(shù)組返回。

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

          請(qǐng)注意 Set 方法僅適用于原始值。

          從數(shù)組中過(guò)濾掉虛假值

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

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

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

          Boolean 是一個(gè)對(duì)象包裝器。在 filter(Boolean) 方法中,數(shù)組中的每一項(xiàng)都被傳入并評(píng)估如下。結(jié)果為真或假,假值將被過(guò)濾掉。

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

          使用 Array.every 和 Array.some 來(lái)簡(jiǎn)化代碼

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

          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');

          總結(jié)

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


          學(xué)習(xí)更多技能

          請(qǐng)點(diǎn)擊下方公眾號(hào)

          瀏覽 58
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产精品毛片3 | 日本一区区在线视频 | 影音先锋麻豆传媒 | 日本黄色视频网站在线观看 | 在线免费看h |