1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        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”,”P(pán)aul”,"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)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            日本三级视频 | 77777色婷婷 | 国产视频黄| 国产成人麻豆免费观看 | 蓝湛被调教嗯啊好深啊 | 久久人妖TS三区系列电影 | 波多野结衣av电影网站 | 91麻豆6部合集magnet | 日韩在线一区二区红桃视频在线观看 | 日韩一级强奸片 |