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

          這樣寫的 JS 代碼看著就很舒服

          共 5611字,需瀏覽 12分鐘

           ·

          2020-11-19 00:02

          來自公眾號:小生方勤

          作者:小生方勤

          如何提高代碼的可讀性、復(fù)用性、擴(kuò)展性。我們將從以下四個方面討論:

          1. 變量
          2. 函數(shù)
          3. 異步

          一、變量

          用有意義且常用的單詞命名

          //?Bad:
          const?yyyymmdstr?=?moment().format('YYYY/MM/DD');
          //?Good:
          const?currentDate?=?moment().format('YYYY/MM/DD');

          保持統(tǒng)一

          對同一類型的變量使用相同的命名保持統(tǒng)一:

          //?Bad:
          getUserInfo();
          getClientData();
          getCustomerRecord();
          //?Good:
          getUser()

          每個常量(全大寫)都該命名

          可以用?ESLint?檢測代碼中未命名的常量。

          //?Bad:
          //?其他人知道 86400000?的意思嗎?
          setTimeout(?blastOff,?86400000?);
          //?Good:
          const?MILLISECOND_IN_A_DAY?=?86400000;
          setTimeout(?blastOff,?MILLISECOND_IN_A_DAY?);

          避免無意義的前綴

          如果創(chuàng)建了一個對象 car,就沒有必要把它的顏色命名為 carColor。

          //?Bad:
          const?car?=?{
          ????carMake:?'Honda',
          ????carModel:?'Accord',
          ????carColor:?'Blue'
          };
          function?paintCar(?car?)?{
          ????car.carColor?=?'Red';
          }
          //?Good:
          const?car?=?{
          ????make:?'Honda',
          ????model:?'Accord',
          ????color:?'Blue'
          };
          function?paintCar(?car?)?{
          ????car.color?=?'Red';
          }

          傳參使用默認(rèn)值

          //?Bad:
          function?createMicrobrewery(?name?)?{
          ????const?breweryName?=?name?||?'Hipster?Brew?Co.';
          ????//?...
          }
          //?Good:
          function?createMicrobrewery(?name?=?'Hipster?Brew?Co.'?)?{
          ????//?...
          }

          二、函數(shù)

          函數(shù)參數(shù)( 最好 2 個或更少 )

          如果參數(shù)超過兩個,建議使用 ES6 的解構(gòu)語法,不用考慮參數(shù)的順序。

          //?Bad:
          function?createMenu(?title,?body,?buttonText,?cancellable?)?{
          ????//?...
          }
          //?Good:
          function?createMenu(?{?title,?body,?buttonText,?cancellable?}?)?{
          ????//?...
          }
          createMenu({
          ????title:?'Foo',
          ????body:?'Bar',
          ????buttonText:?'Baz',
          ????cancellable:?true
          });

          一個方法只做一件事情

          這是一條在軟件工程領(lǐng)域流傳久遠(yuǎn)的規(guī)則。嚴(yán)格遵守這條規(guī)則會讓你的代碼可讀性更好,也更容易重構(gòu)。如果違反這個規(guī)則,那么代碼會很難被測試或者重用。

          //?Bad:
          function?emailClients(?clients?)?{
          ????clients.forEach(?client?=>?{
          ????????const?clientRecord?=?database.lookup(?client?);
          ????????if?(?clientRecord.isActive()?)?{
          ????????????email(?client?);
          ????????}
          ????});
          }
          //?Good:
          function?emailActiveClients(?clients?)?{
          ????clients
          ????????.filter(?isActiveClient?)
          ????????.forEach(?email?);
          }
          function?isActiveClient(?client?)?{
          ????const?clientRecord?=?database.lookup(?client?);????
          ????return?clientRecord.isActive();
          }

          函數(shù)名上體現(xiàn)它的作用

          //?Bad:
          function?addToDate(?date,?month?)?{
          ????//?...
          }
          const?date?=?new?Date();
          //?很難知道是把什么加到日期中
          addToDate(?date,?1?);
          //?Good:
          function?addMonthToDate(?month,?date?)?{
          ????//?...
          }
          const?date?=?new?Date();
          addMonthToDate(?1,?date?);

          刪除重復(fù)代碼,合并相似函數(shù)

          很多時候雖然是同一個功能,但由于一兩個不同點,讓你不得不寫兩個幾乎相同的函數(shù)。

          //?Bad:
          function?showDeveloperList(developers)?{
          ??developers.forEach((developer)?=>?{
          ????const?expectedSalary?=?developer.calculateExpectedSalary();
          ????const?experience?=?developer.getExperience();
          ????const?githubLink?=?developer.getGithubLink();
          ????const?data?=?{
          ??????expectedSalary,
          ??????experience,
          ??????githubLink
          ????};
          ????render(data);
          ??});
          }
          function?showManagerList(managers)?{
          ??managers.forEach((manager)?=>?{
          ????const?expectedSalary?=?manager.calculateExpectedSalary();
          ????const?experience?=?manager.getExperience();
          ????const?portfolio?=?manager.getMBAProjects();
          ????const?data?=?{
          ??????expectedSalary,
          ??????experience,
          ??????portfolio
          ????};
          ????render(data);
          ??});
          }
          //?Good:
          function?showEmployeeList(employees)?{
          ??employees.forEach(employee?=>?{
          ????const?expectedSalary?=?employee.calculateExpectedSalary();
          ????const?experience?=?employee.getExperience();
          ????const?data?=?{
          ??????expectedSalary,
          ??????experience,
          ????};
          ????switch(employee.type)?{
          ??????case?'develop':
          ????????data.githubLink?=?employee.getGithubLink();
          ????????break
          ??????case?'manager':
          ????????data.portfolio?=?employee.getMBAProjects();
          ????????break
          ????}
          ????render(data);
          ??})
          }

          使用 Object.assign 設(shè)置默認(rèn)屬性

          //?Bad:
          const?menuConfig?=?{
          ??title:?null,
          ??body:?'Bar',
          ??buttonText:?null,
          ??cancellable:?true
          };
          function?createMenu(config)?{
          ??config.title?=?config.title?||?'Foo';
          ??config.body?=?config.body?||?'Bar';
          ??config.buttonText?=?config.buttonText?||?'Baz';
          ??config.cancellable?=?config.cancellable?!==?undefined???config.cancellable?:?true;
          }
          createMenu(menuConfig);
          //?Good:
          const?menuConfig?=?{
          ??title:?'Order',
          ??//?不包含?body
          ??buttonText:?'Send',
          ??cancellable:?true
          };
          function?createMenu(config)?{
          ??config?=?Object.assign({
          ????title:?'Foo',
          ????body:?'Bar',
          ????buttonText:?'Baz',
          ????cancellable:?true
          ??},?config);
          ??//?config?:?{title:?"Order",?body:?"Bar",?buttonText:?"Send",?cancellable:?true}
          ??//?...
          }
          createMenu(menuConfig);

          盡量不要寫全局方法

          在 JavaScript 中,永遠(yuǎn)不要污染全局,會在生產(chǎn)環(huán)境中產(chǎn)生難以預(yù)料的 bug。舉個例子,比如你在 Array.prototype 上新增一個 diff 方法來判斷兩個數(shù)組的不同。而你同事也打算做類似的事情,不過他的 diff 方法是用來判斷兩個數(shù)組首位元素的不同。很明顯你們方法會產(chǎn)生沖突,遇到這類問題我們可以用 ES2015/ES6 的語法來對 Array 進(jìn)行擴(kuò)展。

          //?Bad:
          Array.prototype.diff?=?function?diff(comparisonArray)?{
          ??const?hash?=?new?Set(comparisonArray);
          ??return?this.filter(elem?=>?!hash.has(elem));
          };
          //?Good:
          class?SuperArray?extends?Array?{
          ??diff(comparisonArray)?{
          ????const?hash?=?new?Set(comparisonArray);
          ????return?this.filter(elem?=>?!hash.has(elem));????????
          ??}
          }

          盡量別用“非”條件句

          //?Bad:
          function?isDOMNodeNotPresent(node)?{
          ??//?...
          }
          if?(!isDOMNodeNotPresent(node))?{
          ??//?...
          }
          //?Good:
          function?isDOMNodePresent(node)?{
          ??//?...
          }
          if?(isDOMNodePresent(node))?{
          ??//?...
          }

          不要過度優(yōu)化

          現(xiàn)代瀏覽器已經(jīng)在底層做了很多優(yōu)化,過去的很多優(yōu)化方案都是無效的,會浪費你的時間。

          //?Bad:
          //?現(xiàn)代瀏覽器已對此(?緩存 list.length )做了優(yōu)化。
          for?(let?i?=?0,?len?=?list.length;?i???//?...
          }
          //?Good:
          for?(let?i?=?0;?i???//?...
          }

          刪除棄用代碼

          這里沒有實例代碼,刪除就對了

          三、類

          使用 ES6 的 class

          在 ES6 之前,沒有類的語法,只能用構(gòu)造函數(shù)的方式模擬類,可讀性非常差。

          //?Good:
          //?動物
          class?Animal?{
          ??constructor(age)?{
          ????this.age?=?age
          ??};
          ??move()?{};
          }
          //?哺乳動物
          class?Mammal?extends?Animal{
          ??constructor(age,?furColor)?{
          ????super(age);
          ????this.furColor?=?furColor;
          ??};
          ??liveBirth()?{};
          }
          //?人類
          class?Human?extends?Mammal{
          ??constructor(age,?furColor,?languageSpoken)?{
          ????super(age,?furColor);
          ????this.languageSpoken?=?languageSpoken;
          ??};
          ??speak()?{};
          }

          使用鏈?zhǔn)秸{(diào)用

          這種模式相當(dāng)有用,可以在很多庫中都有使用。它讓你的代碼簡潔優(yōu)雅。

          class?Car?{
          ??constructor(make,?model,?color)?{
          ????this.make?=?make;
          ????this.model?=?model;
          ????this.color?=?color;
          ??}

          ??setMake(make)?{
          ????this.make?=?make;
          ??}

          ??setModel(model)?{
          ????this.model?=?model;
          ??}

          ??setColor(color)?{
          ????this.color?=?color;
          ??}

          ??save()?{
          ????console.log(this.make,?this.model,?this.color);
          ??}
          }
          //?Bad:
          const?car?=?new?Car('Ford','F-150','red');
          car.setColor('pink');
          car.save();
          //?Good:
          const?car?=?new?Car('Ford','F-150','red')
          ??.setColor('pink');
          ??.save();

          四、異步

          使用 promise 或者 Async/Await 代替回調(diào)

          //?Bad:
          get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin',?(requestErr,?response)?=>?{
          ??if?(requestErr)?{
          ????console.error(requestErr);
          ??}?else?{
          ????writeFile('article.html',?response.body,?(writeErr)?=>?{
          ??????if?(writeErr)?{
          ????????console.error(writeErr);
          ??????}?else?{
          ????????console.log('File?written');
          ??????}
          ????});
          ??}
          });
          //?Good:
          get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin')
          ??.then((response)?=>?{
          ????return?writeFile('article.html',?response);
          ??})
          ??.then(()?=>?{
          ????console.log('File?written');
          ??})
          ??.catch((err)?=>?{
          ????console.error(err);
          ??});

          //?perfect:
          async?function?getCleanCodeArticle()?{
          ??try?{
          ????const?response?=?await?get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin');
          ????await?writeFile('article.html',?response);
          ????console.log('File?written');
          ??}?catch(err)?{
          ????console.error(err);
          ??}
          }



          最后

          • 關(guān)注公眾號【前端宇宙】,每日獲取好文推薦
          • 添加微信,入群交流

          “在看和轉(zhuǎn)發(fā)”就是最大的支持



          瀏覽 54
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <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>
                  少妇被又大又粗又爽毛片久久黑人 | 午夜精品久久久久久久99蜜桃乐播 | 伊人久久爱 | 大香蕉综合在线观看 | 亚洲AV无码成人精品区在线欢看 |