1. 原文:github.com/ryanmcdermott/clean-code-javascript
  2. 说明:本文翻译自 github 上的一个项目,只取部分精华。

一、变量

用有意义且常用的单词命名

  1. //Bad
  2. const yyyymmdstr=moment().format('YYYY/MM/DD');
  3. //Good
  4. const currentDate=moment().format('YYYY/MM/DD');

保持统一

对同一类型的变量使用相同的命名保持统一:

  1. //Bad:
  2. getUserInfo();
  3. getClientData();
  4. getCustomerRecord();
  5. //Good:
  6. getUser();

每个常量(全大写)都该命名

可以用 ESLint 检测代码中未命名的常量。

  1. //Bad:
  2. //其他人知道86400000的意思吗?
  3. setTimeout(blastoff,864000);
  4. //Good:
  5. const MILLISECOND_IN_A_DAY=86400000;
  6. setTimeout(blastoff,MILLISECOND_IN_A_DAY);

避免无意义的命名

既然创建了一个 car 对象,就没有必要把它的颜色命名为 carColor。

  1. //Bad:
  2. const car={
  3. carMake:'Honda',
  4. carModel:'Accord',
  5. carColor:'Blue'
  6. };
  7. function paintCar(car){
  8. car.carColor='Red';
  9. }
  10. //Good:
  11. const car={
  12. make:'Honda',
  13. model:'Accord',
  14. color:'Blue'
  15. };
  16. function paintCar(car){
  17. car.color='Red';
  18. }

传参使用默认值

  1. //Bad:
  2. function createMicrobrewery(name){
  3. const breweryName=name||'Hipster Brew Co.';
  4. // ...
  5. }
  6. //Good:
  7. function createMicrobrewery(name='Hipster Brew Co.'){
  8. // ...
  9. }

二、函数

函数参数( 最好 2 个或更少 )

如果参数超过两个,建议使用 ES6 的解构语法,不用考虑参数的顺序。

  1. //Bad:
  2. function createMenu(title,body,buttonText,cancellable){
  3. // ...
  4. }
  5. //Good:
  6. function createMenu({title,body.buttonText,cancellable}{
  7. // ...
  8. }
  9.  
  10. createMenu({
  11. title:'Foo',
  12. body:'Bar',
  13. buttonText:'Baz',
  14. cancellable:true
  15. });

一个方法只做一件事情

这是一条在软件工程领域流传久远的规则。严格遵守这条规则会让你的代码可读性更好,也更容易重构。如果违反这个规则,那么代码会很难被测试或者重用。

  1. //Bad:
  2. function emailClients(clients){
  3. clients.foreach(client =>{
  4. const clientRecord = database.lookup(client);
  5. if(clientRecord.isActive()){
  6. email(client);
  7. }
  8. });
  9. }
  10. //Good:
  11. function emailActiveClients(clients){
  12. clients
  13. .filter(isActiveClient)
  14. .forEach(email);
  15. }
  16. function isActiveClient(client){
  17. const clientRecord = database.lookup(client);
  18. return clientRecord.isActive();
  19. }

函数名上体现它的作用

  1. //Bad:
  2. function addToDate(date,month){
  3. // ...
  4. }
  5. const date = new Date();
  6. //很难知道是把什么加到日期中
  7. addToDate(date,1);
  8.  
  9. //Good:
  10. function addMonthToDate(month,date){
  11. // ...
  12. }
  13. const date = new Date();
  14. addMonthToDate(1,date);

删除重复代码,合并相似函数

很多时候虽然是同一个功能,但由于一两个不同点,让你不得不写两个几乎相同的函数。

  1. /Bad:
  2. function showDeveloperList(developers){
  3. developers.forEach((developer)=>{
  4. const expectedSalary = developer.calculateExpectedSalary;
  5. const experience = developer.getExperience();
  6. const githubLink = developer.getGithubLink();
  7. const data={
  8. expectedSalary,
  9. experience,
  10. githubLink
  11. };
  12. render(data);
  13. });
  14. }
  15. function showManagerList(managers){
  16. managers.forEach((manager)=>{
  17. const expectedSalary = manager.calculateExpectedSalary();
  18. const experience = manager.getExperience();
  19. const portfolio = manager.getMBAProjects();
  20. const data={
  21. expectedSalary,
  22. experience,
  23. portfolio
  24. };
  25. render(data);
  26. });
  27. }
  28. //Good:
  29. function showEmployeeList(employees){
  30. employees.forEach((employee)=>{
  31. const expectedSalary = employee.getExpectedSalary();
  32. const experience = employee.getExperience();
  33. const data = {
  34. expectedSalary,
  35. experience,
  36. }
  37. switch(employee.type){
  38. case 'develop':
  39. data.githubLink=employee.getGithubLink();
  40. break;
  41. case 'manager':
  42. data.portfolio = employee.getMBAProjects();
  43. break;
  44. }
  45. render(data);
  46. });
  47. }

使用 Object.assign 设置默认属性

  1. //Bad:
  2. const menuConfig = {
  3. title: null,
  4. body: 'bar',
  5. buttonText: null,
  6. cancellable: true
  7. };
  8. function createMenu(config){
  9. config.title = config.title || 'Foo';
  10. config.body = config.body || 'Bar';
  11. config.buttonText = config.buttonText || 'Baz';
  12. config.cancellable = config.cancellable !== undefined ? config.cancellable:true;
  13. }
  14. createMenu(menuConfig);
  15.  
  16. //Good:
  17. const menuConfig = {
  18. title: 'Order',
  19. //不包含body
  20. buttonText: 'Send',
  21. cancellable: true
  22. };
  23. function createMenu(config){
  24. config = Object.assign({
  25. title: 'Foo',
  26. body: 'Bar',
  27. buttonText: 'Baz',
  28. cancellable:true
  29. },config);
  30.  
  31. // config:{title: "order",body:"Bar",buttonText:"Send",cancellable:true}
  32. // ...
  33. }

尽量不要写全局方法

在 JavaScript 中,永远不要污染全局,会在生产环境中产生难以预料的 bug。举个例子,比如你在 Array.prototype 上新增一个 diff 方法来判断两个数组的不同。而你同事也打算做类似的事情,不过他的 diff 方法是用来判断两个数组首位元素的不同。很明显你们方法会产生冲突,遇到这类问题我们可以用 ES2015/ES6 的语法来对 Array 进行扩展。

  1. //Bad:
  2. Array.prototype.diff = function diff(comparisonArray){
  3. const hash = new Set(comparisonArray);
  4. return this.filter(elem => !hash.has(elem));
  5. };
  6.  
  7. //Good:
  8. class SuperArray extends Array{
  9. diff(comparisonArray){
  10. const hash = new Set(comparisonArray);
  11. return this.filter(elem=> !hash.has(elem));
  12. }
  13. }

尽量别用“非”条件句

  1. //Bad:
  2. function isDOMNodeNotPresent(node){
  3. // ...
  4. }
  5.  
  6. if (!isDOMNodePresent(node)){
  7. // ...
  8. }
  9.  
  10. //Good:
  11. function isDOMNodePresent(node){
  12. // ...
  13. }
  14. if(isDOMNodePresent(node)){
  15. // ...
  16. }

不要过度优化

现代浏览器已经在底层做了很多优化,过去的很多优化方案都是无效的,会浪费你的时间。

  1. //Bad:
  2. // 现代浏览已对此(缓存list.length)做了优化。
  3. for(let i = 0, len = list.length;i < len;i++){
  4. // ...
  5. }
  6.  
  7. //Good:
  8. for(let i = 0; i< list.length; i++){
  9. // ...
  10. }

删除弃用代码

弃用代码不用注释,直接删除就对了

三、类

使用 ES6 的 class

在 ES6 之前,没有类的语法,只能用构造函数的方式模拟类,可读性非常差。

  1. //Good:
  2. // 动物
  3. class Animal{
  4. constructor(age){
  5. this.age = age
  6. };
  7. move() {};
  8. }
  9.  
  10. // 哺乳动物
  11. class Mammal extends Animal{
  12. constructor(age, furcolor){
  13. super(age);
  14. this.furColor = furColor;
  15. };
  16. liveBirth() {};
  17. }
  18.  
  19. //人类
  20. class Human extends Mammal{
  21. constructor(age, furColor, languageSpoken){
  22. super(age,furColor);
  23. this.languageSpoken=languageSpoken;
  24. }
  25. speak() {};
  26. }

使用链式调用

这种模式相当有用,可以在很多库中都有使用。它让你的代码简洁优雅。

  1. class Car{
  2. constructor(make,model,color){
  3. this.make = make;
  4. this.model = model;
  5. this.color = color;
  6. }
  7.  
  8. setMake(make){
  9. this.make = make;
  10. }
  11.  
  12. setModel(model){
  13. this.model = model;
  14. }
  15.  
  16. setColor(color){
  17. this.color = color;
  18. }
  19.  
  20. save(){
  21. console.log(this.make, this.model., this.color);
  22. }
  23. }
  24.  
  25. // Bad:
  26. const car = new Car('Ford','F-150','red');
  27. car.setColor('pink');
  28. car.save();
  29.  
  30. //Good:
  31. const car = new Car('Ford','F-150','red')
  32. .setColor('pink')
  33. .save();

四、异步

使用 promise 或者 Async/Await 代替回调

  1. //Bad:
  2. get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin',(requestErr,response) => {
  3. if(requestErr){
  4. consoloe.error(requestErr);
  5. }else{
  6. writeFile('article.html',response.body,(writeErr) => {
  7. if(writeErr){
  8. console.error(writeErr);
  9. }else {
  10. console.log('File written');
  11. }
  12. })
  13. }
  14. });
  15.  
  16. //Good:
  17. get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin')
  18. .then((response) => {
  19. return writeFile('article.html' ,response);
  20. })
  21. .then( (response) => {
  22. console.log('File written');
  23. })
  24. .catch( (err) => {
  25. console.error(err);
  26. });
  27.  
  28. //perfect:
  29. async function getCleanCodeArticle(){
  30. try{
  31. const response = await get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin');
  32. await writeFile('artical.html',response);
  33. console.log('File written');
  34. }catch (err){
  35. console.error(err);
  36. }
  37. }

JS编程规范指南的更多相关文章

  1. JS编程规范

    在第一家公司用C++时,公司有着严格的代码规范,甚至到了严苛的地步,现在回想起来,对它充满感激.一个好的习惯让你收益终身. 之后使用JS/TS却没有为自己定一套编程规范,所幸为时不晚,在这里参考air ...

  2. Node.js编程规范

    摘自:https://github.com/dead-horse/node-style-guide https://github.com/felixge/node-style-guide 2空格缩进 ...

  3. tensorflow2.0编程规范

    背景 tensorflow2.0 相比于1.0 有很大变化,1.0版本的placeholder,Session都没有了,2.0版本强推使用keras.keras是一个比较高层的api,确实挺好用的,一 ...

  4. Batsing的网页编程规范(HTML/CSS/JS/PHP)

    特别注意!!!我这里的前端编程规范不苟同于Bootstrap的前端规范. 因为我和它的目的不同,Bootstrap规范是极简主义,甚至有些没有考虑到兼容性的问题. 我的规范是自己从编程实践中总结出来的 ...

  5. Google的Java编程风格指南(Java编码规范)

    这份文档是Google Java编程风格规范的完整定义.当且仅当一个Java源文件符合此文档中的规则, 我们才认为它符合Google的Java编程风格. 与其它的编程风格指南一样,这里所讨论的不仅仅是 ...

  6. .NET编程规范

    .NET开发编程规范 第1章 程序的版式 版式虽然不会影响程序的功能,但会影响可读性.程序的版式追求清晰.美观,是程序风格的重要构成因素. 可以把程序的版式比喻为"书法".好的&q ...

  7. JavaScript编码规范指南

    前言 本文摘自Google JavaScript编码规范指南,截取了其中比较容易理解与遵循的点作为团队的JavaScript编码规范. JavaScript 语言规范 变量 声明变量必须加上 var  ...

  8. Google Java编程风格指南

    出处:http://hawstein.com/posts/google-java-style.html 声明:本文采用以下协议进行授权: 自由转载-非商用-非衍生-保持署名|Creative Comm ...

  9. 谷歌Java编程规范

    Google Java编程风格指南 January 20, 2014 作者:Hawstein 出处:http://hawstein.com/posts/google-java-style.html 声 ...

随机推荐

  1. 2018年第九届蓝桥杯国赛试题(JavaA组)

    1.结果填空 (满分13分)2.结果填空 (满分39分)3.代码填空 (满分27分)4.程序设计(满分45分)5.程序设计(满分71分)6.程序设计(满分105分) 1.标题:三角形面积 已知三角形三 ...

  2. 洛谷P1349 广义斐波那契数列(矩阵快速幂)

    P1349 广义斐波那契数列 https://www.luogu.org/problemnew/show/P1349 题目描述 广义的斐波那契数列是指形如an=p*an-1+q*an-2的数列.今给定 ...

  3. 解析Xml文件的三种方式

    1.Sax解析(simple api  for xml) 使用流式处理的方式,它并不记录所读内容的相关信息.它是一种以事件为驱动的XML API,解析速度快,占用内存少.使用回调函数来实现. clas ...

  4. C++类型起别名的方式

    C++给类型起别名的方式: #include <iostream> using namespace std; #define DString std::string //! 不建议使用!t ...

  5. 使用ffmpeg编码时,如何设置恒定码率,并控制好关键帧I帧间隔

    1. 大家在使用ffmpeg进行视频编码时,使用-b命令,想控制比特率,却发现结果并没有如我们设置所愿,通过码流分析器观察视频码流,码率的波动还是很大的,ffmpeg控制的并不好,这时候,我们可以通过 ...

  6. 2014 Noip提高组 Day1

    P1328 生活大爆炸版石头剪刀布 [题目描述] 石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头.如果两个人出拳一样,则不分胜负.在<生活大爆炸>第二季第8 集中出现了一种石头 ...

  7. 免打包:简单、灵活、便捷的APP渠道统计方法

    相信做过APP运营推广的小伙伴们应该对APP渠道统计并不陌生吧.APP推广运营人员需要根据数据来评估渠道推广的效果,找到最适合自家APP的渠道,有针对性的投放,不断完善推广策略,这样才能更加精准.有效 ...

  8. ReentrantLock锁 源码分析

    根据下面代码分析下ReentrantLock 获得锁和释放锁的过程 ReentrantLock lock = new ReentrantLock(); lock.lock();//获得锁 lock.u ...

  9. 解决phpwind 9 转换到 discuz x 3.1的头像仍然不显示问题

    phpwind 9 转换到 discuz x 3.1后,按照discuz转换程序的步骤做,头像仍然不显示,后来登录后重新上传头像发现,是文件名的原因,如下操作改名即可(还好我的论坛会员不多,不然手改累 ...

  10. vue中声明式导航和编程式导航

    官方文档:https://router.vuejs.org/zh-cn/essentials/navigation.html 声明式导航和编程式导航 共同点: 都能进行导航,都可以触发路由,实现组件切 ...