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

          8 種技巧讓你編寫更簡潔的 JavaScript 代碼

          共 9355字,需瀏覽 19分鐘

           ·

          2022-05-19 23:46

          8 種技巧讓你編寫更簡潔的 JavaScript 代碼

          image-20220430205940938

          大家好,我是速凍魚??,一條水系前端??,喜歡花里胡哨??,持續(xù)沙雕??,是隔壁寒草??的好兄弟。歡迎小伙伴們加我微信:sudongyuer拉你進(jìn)群,一起討論,期待與大家共同成長??。

          在本文中,我們將介紹 8 種不同的技術(shù)來幫助您編寫更簡潔的 JavaScript 代碼。

          現(xiàn)在讓我們討論每種技術(shù),一次一個(gè)。

          純函數(shù)

          純函數(shù)是在給定相同輸入的情況下始終返回相同輸出的函數(shù)。除了提供的輸入之外,它不依賴于任何外部變量,也不影響/更改任何外部變量。擁有純函數(shù)使測試變得更加容易,因?yàn)樗鼈兪箿y試變得超級容易,因?yàn)槟梢噪S時(shí)存根/模擬輸入并測試您的預(yù)期值。讓我們看看下面的例子

          let?name?=?"Yu?DongSu";
          const?splitName?=?()?=>?{
          ??name?=?name.split('?');
          }
          name?=?splitName();
          console.log(name);?//?outputs?[?'Yu',?'DongSu'?]

          雖然上面的代碼看起來很合適。不是開玩笑。這是因?yàn)樵?code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">splitName函數(shù)依賴于一個(gè)名為的外部變量name,如果其他人開始更改此變量,該函數(shù)將splitName開始提供不同的輸出。使它成為一個(gè)非純函數(shù),因?yàn)槲覀內(nèi)匀粫{(diào)用splitName()它,但輸出會有所不同。

          讓我們把它改成一個(gè)純函數(shù),看看它是什么樣子的:

          let?name?=?"Yu?DongSu";
          const?splitName?=?(nameString)?=>?{
          ??return?nameString.split('?');
          }
          name?=?splitName(name);
          console.log(name);?//?outputs?[?'Yu',?'DongSu'?]

          通過上述更改,splitName現(xiàn)在是一個(gè)純函數(shù),因?yàn)椋?/p>

          • 它僅依賴于輸入(nameString輸入)。
          • 它不會更改/重新分配任何外部變量

          更少或命名參數(shù)

          使用函數(shù)時(shí),我們經(jīng)常使用位置參數(shù),這些參數(shù)必須在函數(shù)聲明中聲明時(shí)提供。例如,在 call中,如果不提供and arithmaticOp(num1, num2, operator),我們就無法提供operator參數(shù)。雖然這適用于這個(gè)例子,但對于許多功能來說,這會成為一個(gè)問題。考慮以下示例:

          const?createButton?=?(title,?color,?disabled,?padding,?margin,?border,?shadow)??=>?{
          ??console.log(title,?color,?disabled,?padding,?margin,?border,?shadow)
          }

          查看上面的代碼,您已經(jīng)可以看到,如果我們想在調(diào)用createButton+ 時(shí)將任何參數(shù)設(shè)為可選(使用默認(rèn)值),那將是一場災(zāi)難,可能看起來像這樣:

          createButton('Sudongyu?er',?undefined?/*?optional?color?*/,?true?,'2px....',?undefined??/*?optional?margin*/);

          你可以看到上面的語句看起來一點(diǎn)也不干凈。此外,從函數(shù)調(diào)用語句中很難看出哪個(gè)參數(shù)對應(yīng)于函數(shù)的哪個(gè)參數(shù)。所以這是我們可以遵循的做法:

          • 如果我們有 2 個(gè)或更少的參數(shù),我們可以將它們保留為位置參數(shù)
          • 否則,我們提供一個(gè)帶有鍵值對的對象

          讓我們在上面的例子中使用這個(gè)技術(shù),看看它是什么樣子的:

          const?createButton?=?({title,?color,?disabled,?padding,?margin,?border,?shadow})??=>?{
          ??console.log(title,?color,?disabled,?padding,?margin,?border,?shadow)
          }

          createButton({
          ??title:?'Sudongyu?er',
          ??disabled:?true,
          ??shadow:?'2px....'
          });

          請注意,調(diào)用createButton函數(shù)的語句現(xiàn)在更簡潔了。我們可以很容易地看到鍵值對中的哪個(gè)值對應(yīng)于函數(shù)的參數(shù)。耶耶!??

          對象/數(shù)組解構(gòu)

          考慮以下 javascript 示例,其中我們從對象中獲取一些屬性并分配給它們的各個(gè)變量:

          const?user?=?{
          ??name:?'Sudongyu',
          ??email:?'hi@xxx',
          ??designation:?'Software?Architect',
          ??loves:?'The?Code'
          }

          const?name?=?user.name;
          const?email?=?user.email;
          const?loves?=?user.loves;

          在上面的例子中,多次使用這個(gè)user.*符號是非常令人惡心的。這就是對象解構(gòu)的用武之地。我們可以使用對象解構(gòu)將上面的示例更改如下:

          const?user?=?{
          ??name:?'Sudongyu',
          ??email:?'hi@xxx',
          ??designation:?'Software?Architect',
          ??loves:?'The?Code'
          }

          const?{name,?email,?loves}?=?user;

          看!好多了。對?讓我們考慮另一個(gè)例子:

          const?getDetails?=?()?=>?{
          ??return?['xxx',?'sudongyu',?'Some?Street',?'Some?City',?'Some?Zip',?'Some?Country'];
          }

          const?details?=?getDetails();
          const?uName?=?details[0];
          const?uEmail?=?details[1];
          const?uAddress?=?`${details[2]},?${details[3]},?${details[4]},?${details[5]}`;
          const?uFirstName?=?uName.split('?')[0];
          const?uLastName?=?uName.split('?')[1];

          啊。我什至討厭編寫上述示例的代碼??。雖然不得不這樣做。您可以看到代碼看起來非常怪異且難以閱讀。我們可以使用 Array Destructuring 將其寫得更簡潔,如下所示:

          const?getDetails?=?()?=>?{
          ??return?['xxx',?'sudongyu',?'Some?Street',?'Some?City',?'Some?Zip',?'Some?Country'];
          }
          const?[uName,?uEmail,?...uAddressArr]?=?getDetails();
          const?uAddress?=?uAddressArr.join(',?');
          const?[uFirstName,?uLastName]?=?uName.split('');
          console.log({
          ??uFirstName,
          ??uLastName,
          ??uEmail,
          ??uAddress
          });

          你可以看到這有多干凈??

          避免硬編碼值

          /**
          ?*?阿巴阿巴
          ?*?
          ?*?
          ?*?
          ?*?
          ?*?
          ?*/


          setInterval(()?=>?{
          ??//?do?something
          },?86400000);
          //?WHAT?IS?THIS?86400000???????

          看代碼的人可能不知道這個(gè)數(shù)字代表什么,它是如何計(jì)算的,以及它背后的業(yè)務(wù)邏輯是什么。我們可以創(chuàng)建一個(gè)常量,而不是硬編碼這個(gè)值,如下所示:

          const?DAY_IN_MILLISECONDS?=?3600?*?24?*?1000;?//?86400000

          setInterval(()?=>?{
          ??//?do?something
          },?DAY_IN_MILLISECONDS);
          //?now?this?makes?sense

          讓我們考慮另一個(gè)例子:

          const?createUser?=?(name,?designation,?type)?=>?{
          ??console.log({name,?designation,?type});
          }

          createUser('SudongYu',?'Software?Architect',?'1');
          //?WHAT?IS?this?'1'????

          查看調(diào)用createUser方法。閱讀代碼的人很難理解這'1'代表什么。即type這是什么用戶。因此,我們可以創(chuàng)建一個(gè)我們擁有的用戶類型的對象映射,而不是在這里對值進(jìn)行硬編碼'1',如下所示:

          const?USER_TYPES?=?{
          ??REGULAR_EMPLOYEE:?'1'
          }

          const?createUser?=?(name,?designation,?type)?=>?{
          ??console.log({name,?designation,?type});
          }

          createUser('Sudongyu',?'Software?Architect',?USER_TYPES.REGULAR_EMPLOYEE);
          //?smoooooooth???

          避免使用簡寫變量名

          速記變量在需要它們的地方才有意義。就像如果你有像xand這樣的位置坐標(biāo)y,那是可行的。p但是,如果我們在沒有上下文的情況下創(chuàng)建像,t之類的變量c,那么真的很難閱讀、跟蹤和維護(hù)這樣的代碼。例如看這個(gè)例子:

          const?t?=?25;

          let?users?=?['Sudongyuer',?'xxx'];

          users?=?users.map((user)?=>?{
          ??/**
          ???*?
          ???*?
          ???*?
          ???*?
          ???*?
          ???*?
          ???*?
          ???*?
          ???*?
          ???*?
          ???*?
          ???*?
          ???*?
          ???*?
          ???*?
          ???*?
          ???*?
          ???*?
          ???*?
          ???*?
          ???*?
          ???*?
          ???*?
          ???*?
          ???*/


          ??return?{
          ????...user,
          ????tax:?user.salary?*?t?/?100?//?WHAT?IS?`t`?again????
          ??}
          })

          上面的例子表明,現(xiàn)在開發(fā)人員/讀者必須一直向上滾動或轉(zhuǎn)到定義來嘗試?yán)斫膺@個(gè)變量是什么。因此是不干凈的代碼??。這也稱為對變量進(jìn)行思維導(dǎo)圖,其中只有作者知道它們的含義。因此,我們可以給它一個(gè)適當(dāng)?shù)拿Q,而不是簡寫變量名稱,如下所示:

          const?taxFactor?=?25;

          let?users?=?['Sudongyuer',?'xxx'];

          users?=?users.map((user)?=>?{
          ??//?some?code
          ??return?{
          ????...user,
          ????tax:?user.salary?*?taxFactor?/?100
          ??}
          })

          現(xiàn)在這更有意義了。

          使用 Object.assign() 設(shè)置默認(rèn)對象值

          在某些情況下,您可能希望從另一個(gè)對象創(chuàng)建一個(gè)新對象,如果源對象沒有它們,則提供一些默認(rèn)值。考慮以下示例:

          const?createButton?=?({title,?color,?disabled,?padding})??=>?{
          ??const?button?=?{};
          ??button.color?=?color?||?'#333';
          ??button.disabled?=?disabled?||?false;
          ??button.title?=?title?||?'';
          ??button.padding?=?padding?||?0;
          ??return?button;
          }

          const?buttonConfig?=?{
          ??title:?'Click?me!',
          ??disabled:?true
          }

          const?newButton?=?createButton(buttonConfig);
          console.log('newButton',?newButton)

          Object.assign()如果源對象提供了默認(rèn)屬性,我們可以使用如下方式覆蓋默認(rèn)屬性,而不是做所有這些:

          const?createButton?=?(config)??=>?{
          ??return?{
          ????...{
          ??????color:?'#dcdcdc',
          ??????disabled:?false,
          ??????title:?'',
          ??????padding:?0
          ????},
          ????...config?
          ??};
          }

          const?buttonConfig?=?{
          ??title:?'Click?me!',
          ??disabled:?true
          }

          const?newButton?=?createButton(buttonConfig);
          console.log('newButton',?newButton)

          使用方法鏈(尤其是類)

          如果我們知道類/對象的用戶將一起使用多個(gè)函數(shù),則方法鏈接是一種很有用的技術(shù)。您可能已經(jīng)在諸如 moment.js 之類的庫中看到了這一點(diǎn)。讓我們看一個(gè)例子:

          class?Player?{
          ??constructor?(name,?score,?position)?{
          ????this.position?=?position;
          ????this.score?=?score;
          ????this.name?=?name;
          ??}
          ??setName(name)?{
          ????this.name?=?name;
          ??}
          ??setPosition(position)?{
          ????this.position?=?position;
          ??}
          ??setScore(score)?{
          ????this.score?=?score;
          ??}
          }

          const?player?=?new?Player();
          player.setScore(0);
          player.setName('Sudongyuer');
          player..setPosition([2,?0]);
          console.log(player)

          在上面的代碼中,您可以看到我們需要為播放器一起調(diào)用一堆函數(shù)。如果您的對象/類是這種情況,請使用方法鏈接。您需要做的就是從要鏈接的函數(shù)中返回對象的實(shí)例。上面的例子可以修改如下來實(shí)現(xiàn):

          class?Player?{
          ??constructor?(name,?score,?position)?{
          ????this.position?=?position;
          ????this.score?=?score;
          ????this.name?=?name;
          ??}
          ??setName(name)?{
          ????this.name?=?name;
          ????return?this;?//?<--?THIS
          ??}
          ??setPosition(position)?{
          ????this.position?=?position;
          ????return?this;?//?<--?THIS
          ??}
          ??setScore(score)?{
          ????this.score?=?score;
          ????return?this;?//?<--?THIS
          ??}
          }

          const?player?=?new?Player();
          player.setScore(0).setName('Sudongyuer').setPosition([2,?0]);
          //?SUPER?COOL???
          console.log(player)

          在回調(diào)上使用 Promise

          承諾讓我們的生活更輕松。幾年前我們有一個(gè)叫做回調(diào)地獄的東西,這使得代碼很難閱讀。它看起來像這樣:

          圖片描述

          即使我正在使用具有回調(diào)的庫,我也會嘗試在那里添加一個(gè)包裝器來保證這一點(diǎn)(是的,現(xiàn)在這是一個(gè)術(shù)語)。讓我們考慮以下示例:

          ?const?getSocials?=?(callback)?=>?{
          ??setTimeout(()?=>?{
          ??????callback({socials:?{youtube:?'xxx',?twitter:?'xxx'}});
          ????},?1500);
          }

          const?getBooks?=?(callback)?=>?{
          ??setTimeout(()?=>?{
          ????callback({books:?['React?Cookbook']});
          ??},?1500);
          }

          const?getDesignation?=?(callback)?=>?{
          ??setTimeout(()?=>?{
          ????callback({designation:?'Software?Architect'});
          ??},?1500);
          }

          const?getUser?=?(callback)?=>?{
          ??setTimeout(()?=>?{
          ????callback({user:?'Sudongyuer'});
          ??},?1500);
          }

          ?getUser(({user})?=>?{
          ????console.log('user?retrieved',?user)
          ????getDesignation(({designation})?=>?{
          ??????console.log('designation?retrieved',?designation)
          ??????getBooks(({books})?=>?{
          ????????console.log('books?retrieved',?books)
          ????????getSocials(({socials})?=>?{
          ??????????console.log('socials?retrieved',?socials)
          ????????})
          ??????})
          ????})
          ??})

          上述代碼中的所有函數(shù)都是異步的,它們會在 1.5 秒后發(fā)回?cái)?shù)據(jù)。現(xiàn)在,如果涉及 15 個(gè)不同的功能,想象一下它會是什么樣子。可能就像我在上面分享的圖像??。為了更好的可讀性,我們可以promisify我們的函數(shù)并使用promises,而不是這個(gè)回調(diào)地獄:

          const?getSocials?=?()?=>?{
          ??return?new?Promise(resolve?=>?{
          ????setTimeout(()?=>?{
          ??????resolve({socials:?{youtube:?'xxx',?twitter:?'xxx'}});
          ????},?1500);
          ??})

          }

          const?getBooks?=?()?=>?{
          ??return?new?Promise(resolve?=>?{
          ????setTimeout(()?=>?{
          ??????resolve({books:?['React?Cookbook']});
          ????},?1500);
          ??})
          }

          const?getDesignation?=?()?=>?{
          ??return?new?Promise(resolve?=>?{
          ????setTimeout(()?=>?{
          ??????resolve({designation:?'Software?Architect'});
          ????},?1500);
          ??})
          }

          const?getUser?=?()?=>?{
          ??return?new?Promise(resolve?=>?{
          ????setTimeout(()?=>?{
          ??????resolve({user:?'Sudongyuer'});
          ????},?1500);
          ??})
          }

          ??getUser()
          ????.then(({user})?=>?{
          ??????console.log('user?retrieved',?user);
          ??????return?getDesignation();
          ????})
          ????.then(({designation})?=>?{
          ??????console.log('designation?retrieved',?designation)
          ??????return?getBooks();
          ????})
          ????.then(({books})?=>?{
          ??????console.log('books?retrieved',?books);
          ??????return?getSocials();
          ????})
          ????.then(({socials})?=>?{
          ??????console.log('socials?retrieved',?socials)
          ????})

          您可以看到代碼現(xiàn)在已經(jīng)非常可讀,因?yàn)樗姓Z句都縮進(jìn)并顯示了在每個(gè)步驟.then()中檢索到的數(shù)據(jù)。.then()我們可以很容易地看到使用這種語法的步驟,因?yàn)槊看?code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">.then()調(diào)用都會返回下一個(gè)函數(shù)調(diào)用及其承諾。

          現(xiàn)在我們可以把它提升一個(gè)檔次,讓我們的代碼更具可讀性。如何?通過使用async await. 我們將修改我們的代碼如下來實(shí)現(xiàn):

          const?getSocials?=?()?=>?{
          ??return?new?Promise(resolve?=>?{
          ????setTimeout(()?=>?{
          ??????resolve({socials:?{youtube:?'xxx',?twitter:?'xxx'}});
          ????},?1500);
          ??})

          }

          const?getBooks?=?()?=>?{
          ??return?new?Promise(resolve?=>?{
          ????setTimeout(()?=>?{
          ??????resolve({books:?['React?Cookbook']});
          ????},?1500);
          ??})
          }

          const?getDesignation?=?()?=>?{
          ??return?new?Promise(resolve?=>?{
          ????setTimeout(()?=>?{
          ??????resolve({designation:?'Software?Architect'});
          ????},?1500);
          ??})
          }

          const?getUser?=?()?=>?{
          ??return?new?Promise(resolve?=>?{
          ????setTimeout(()?=>?{
          ??????resolve({user:?'Sudongyuer'});
          ????},?1500);
          ??})
          }

          const?performTasks?=?async?()?=>?{
          ??const?{user}?=?await?getUser();
          ??console.log('user?retrieved',?user);

          ??const?{designation}?=?await?getDesignation();
          ??console.log('designation?retrieved',?designation);

          ??const?{books}?=?await?getBooks();
          ??console.log('books?retrieved',?books);

          ??const?{socials}?=?await?getSocials();
          ??console.log('socials?retrieved',?socials);
          }

          請注意,我們將代碼包裝在performTasks()函數(shù)中,這是一個(gè)async函數(shù),您可以看到async關(guān)鍵字的用法。在內(nèi)部,我們使用await關(guān)鍵字進(jìn)行每個(gè)函數(shù)調(diào)用,這基本上會在執(zhí)行下一行代碼之前等待函數(shù)的承諾得到解決。使用這種語法,我們的代碼看起來好像都是同步的,但實(shí)際上是異步的。而且我們的代碼更干凈??

          結(jié)論

          那么我的編寫更簡潔的 JavaScript 代碼的 8 種技巧這篇文章就結(jié)束了,文章的目的其實(shí)很簡單,就是對日常工作的總結(jié)和輸出,輸出一些覺得對大家有用的東西,菜不菜不重要,但是熱愛??,希望大家能夠喜歡我的文章,我真的很用心在寫,也希望通過文章認(rèn)識更多志同道合的朋友,如果你也喜歡折騰,歡迎加我好友,一起沙雕,一起進(jìn)步


          往期干貨

          ?26個(gè)經(jīng)典微信小程序+35套微信小程序源碼+微信小程序合集源碼下載(免費(fèi))

          ?干貨~~~2021最新前端學(xué)習(xí)視頻~~速度領(lǐng)取

          ?前端書籍-前端290本高清pdf電子書打包下載


          點(diǎn)贊和在看就是最大的支持??


          瀏覽 40
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(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>
                  18禁免费网址 | 97福利视频| 亚洲骚逼| 国产青娱视频在线观看 | 亚洲自拍小视频在线观看 |