乐趣区

关于前端:编写高质量可维护的代码一目了然的注释

71 篇原创好文~
本文首发于政采云前端团队博客:编写高质量可保护的代码:高深莫测的正文

前言

​ 有一些人认为,好的代码是自我解释的。适合的命名和优良的代码确实能够加重开发人员浏览代码的工作量,对于不是特地简单的代码可能的确能够做到自我解释。但并不是所有场景都能够做到这一点,咱们一起来理解一下“正文”吧。

编程语言中对“正文”的解释

​ 正文就是对代码的解释和阐明。正文是开发人员在编写程序时,给一段代码的解释或提醒,有助于进步程序代码的可读性。正文不会被计算机编译。

要不要加正文?为什么要加正文?

​ 正文的存在就是为了不便本人的二次浏览和代码保护以及我的项目交接。能够更好的了解代码,有助于进步合作效率,放慢开发过程。

​ 试想,你增加了一段逻辑较为简单的代码,几个月后再看,还能不能迅速看懂?你刚刚接手一个老我的项目,我的项目里根本没有正文且逻辑简单,你能高效率的看懂代码和理解业务吗?

​ 所以增加正文还是有肯定必要滴。

根底篇

快捷键 windows 零碎:Ctrl+/ ios 零碎:Command+/

正文的分类

  • HTML 中的正文
<div>
  这是一行文字
  <!-- 这是一行被正文的文字 -->
</div>
  • CSS 中的正文

    • 在 HTML 中
    <style>
      div {/* color: #fff;  */}
    </style>
    • 在 .css 文件中
    div {/* color: #fff;  */}
    • 在 .less 或 .scss 文件中
    div {
        /* color: #fff;*/  /* 多行正文 */
        // font-size: 14px; // 单行正文
        background: #000;
    }
  • JS 中的正文

    • 用法

      * 可用于解释 JavaScript 代码,加强其可读性。* 也能够用于阻止代码执行。
    • 单行正文(行正文)—— 以 // 结尾。任何位于 // 之后的文本都会被正文

      // 定义一个空数组
      var ary = [];
      var ary2 = []; // 又定义一个空数组
* 多行正文(块正文)——以 `/*` 结尾,以 `*/` 结尾。任何位于 `/*` 和 `*/` 之间的文本都会被正文

```js
/*
    这是多行正文
    定义一个数组
 */
var ary = [];
```



* 用正文来阻止代码执行  —— 被正文的 JS 代码将不被执行

```js
//alert("123")  // 执行时未弹出该信息
alert("456")  // 执行时弹出该信息
```


  • 函数正文

    • 个别以 /** 结尾,以 */ 结尾。任何位于 /***/之间的文本都会被正文
/**
 * 提交
 *
 * @method onSubmit
 * @param {[Object]} 提交数据
 * @return  {[Bollean]}  [返回是否提交胜利]
 */
const onSubmit = (params = {}) => {
  const result = false;
    if (params) {result = true;}
    return result;
};
  • 非凡标记正文

    • TODO在该正文处有性能代码待编写,待实现的性能在阐明中会简略阐明
    • FIXME在该正文处代码须要修改,甚至代码是谬误的,不能工作,须要修复,如何修改会在阐明中简略阐明
    • XXX在该正文处代码尽管实现了性能,然而实现的办法有待商讨,心愿未来能改良,要改良的中央会在阐明中简略阐明
    • NOTE在该正文处阐明代码如何工作
    • HACK在该正文处编写得不好或格局谬误,须要依据本人的需要去调整程序代码
    • BUG在该正文处有 Bug
// TODO 性能未实现,待欠缺
// FIXME  待修复
// XXX    实现办法待确认
// NOTE   代码性能阐明
// HACK   此处写法有待优化
// BUG    此处有 Bug
const arr = []

Tips:

  • 为什么 // 正文能够在 .less 或 .scss 文件中应用,然而在 .html 和 .css 文件中不失效?

    • 在 MDN 中对于 CSS 正文只有 /* */ 一种语法。然而在 LESS 和 SCSS 中反对正文的语法和 js 中保持一致,有单行正文 // 和多行正文 /* */ 两种。单行正文编译之后不会被保留。
  • 单行正文为什么有时候写在代码上方,有时候写在代码前方?

    • 正文能够书写在代码中的任意地位。集体了解,个别写在代码上方的时候意为对前面一段代码的正文,而写在代码前方的时候意为对本行代码的正文。

正文写法标准

  • 文件正文

    • 位于文件头部,个别蕴含概要、作者、版本改变信息以及批改工夫等内容
  /*
   * 简述以后文件性能
   * @author 作者名称
   * @version 版本号 最近编辑工夫
   * @description 该版本改变信息
   */
  • 单行正文

    • 总是在 // 后留一个空格
  // 这是一行正文
  • 多行正文

    • 总是放弃星号纵向对齐(结束符前留一个空格)
    • 不要在开始符、结束符所在行写正文
    • 尽量应用单行正文代替多行正文
    • 正文函数时,举荐应用多行正文
  /*
    这里有一行正文
    这里有一行正文
    这里有一行正文
   */
  • 函数正文

    • 其间每一行都以 * 结尾,且与第一行第一个 * 对齐
    • 正文内容与 * 间留一个空格
    • 必须蕴含标签正文。例:
/**
* 办法阐明
* @method 办法名
* @for 所属类名
* @param {参数类型} 参数名 参数阐明
* @return {返回值类型} 返回值阐明
*/

正文罕用标签用法

  • @type {typeName}

    • *示意任何类型
    • ?示意能够为null
    • !示意不能为null
    • []示意数组
/**
* @type {number}
*/
var foo1;

/**
* @type {*}
* @desc 任何类型
*/
var foo2;

/**
* @type {?string}
* @desc string 或者 null
*/
var foo3;
  • @param {<type>} name – some description

    • 非必传参数需给参数名加上 '[]’
    • 参数如有默认值需用 ’=’ 示意
    • 如果参数是 object,可持续用 @param 对其属性进行具体阐明
    • 若干个参数用 ... 示意
/**
 * @func
 * @desc 一个带参数的函数
 * @param {string} a - 参数 a
 * @param {number} b=1 - 参数 b 默认值为 1
 * @param {string} c=1 - 参数 c 有两种反对的取值  1—示意 x  2—示意 xx
 * @param {object} d - 参数 d 为一个对象
 * @param {string} d.e - 参数 d 的 e 属性
 * @param {object[]} g - 参数 g 为一个对象数组
 * @param {string} g.h - 参数 g 数组中一项的 h 属性
 * @param {string} [j] - 参数 j 是一个可选参数
 */
 function foo(a, b, c, d, g, j) {}

/**
 * @func
 * @desc 一个带若干参数的函数
 * @param {...string} a - 参数 a
 */
function bar(a) {}

理解更多可查看 JSDoc

拓展篇

IE 条件正文(IE5+)

IE 条件正文分为以下几种状况:

  • 只容许 IE 解释执行 <!--[if IE]><![endif]-->
  • 只容许 IE 特定版本解释执行 <!--[if IE 7]><![endif]-->
  • 只容许非 IE 特定版本执行正文 <!--[if !IE 7]><![endif]-->
  • 只容许高于或低于 IE 特定版本执行正文 <!--[if gt IE 7]><![endif]-->
 <head>
      <title>IE 条件正文 </title>
  
      <!-- 是 IE 时 -->
    <!--[if IE]> 
        <link href="style.css" rel="stylesheet" type="text/css" />
    <![endif]-->
  
    <!-- 是 IE 7 时 -->
          <!--[if IE 7]>
       <link href="style.css" rel="stylesheet" type="text/css" />
    <![endif]-->
 
    <!-- 不是 IE 7 时 -->
      <!--[if !IE 7]>
        <link href="style.css" rel="stylesheet" type="text/css" />
    <![endif]-->
  
      <!-- 大于 IE 7 时 -->
      <!--[if gt IE 7]>
       <link href="style.css" rel="stylesheet" type="text/css" />
    <![endif]-->
 
      <!-- 小于 IE 7 时 -->
       <!--[if lt IE 7]>
       <link href="style.css" rel="stylesheet" type="text/css" />
    <![endif]-->
</head>

(井号)正文 和 ”’(三引号)正文

  • #个别呈现在各种脚本配置文件中,用法与 JS 单行正文 // 基本相同。Python 中也经常用到
  • '''是 Python 中的多行正文语法,用 ''' ''' 蕴含被正文的段落
# python 的单行正文一
    print("I could have code like this.") # python 的单行正文二

# print("This won't run.") # 被正文的代码'''
    被三引号包裹的段落
    能够随便折行
    也能够正文代码
    print("This won't run.")'''

正文“被执行”了?

​ 家喻户晓,正文的代码是不会被执行的。然而小编在查资料时看到了一段比拟有意思的代码,Java 中的一行正文“被执行”了?

public class Test {public static void main(String[] args) {
        String name = "赵大";
        // \u000dname="钱二";
        System.out.println(name);
    }
}

​ 这段代码执行后的后果为 钱二,也就是说在这段代码中,“被正文”的那行代码失效了!

​ 这段代码的问题出在 \u000d 这串特殊字符上。\u000d是一串 Unicode 字符,代表换行符。Java 编译器不仅会编译代码,还会解析 Unicode 字符。在下面这段代码把 \u000d 给解析了,前面的代码就到了上面一行,超出了被正文的范畴(单行正文的正文范畴仅在以后行),所以执行后果为 钱二 而非 赵大。(如下)

public class Test {public static void main(String[] args) {
        String name = "赵大";
        //
        name="钱二";
        System.out.println(name);
    }
}

​ 所以实质上在代码执行的时候 name="钱二"并没有被正文,而是被换了行(奇怪的常识减少了)。所以切记,正文的确是不会被执行的哦!

正文相干插件

​ 在这里举荐几个集体认为比拟好用的正文相干的 Vscode 插件,可在 setting.json 文件下自定义设置(可通过 ‘ 文件—首选项—设置 ’,关上 Vscode 文件settings.json

  • koroFileHeader 在 vscode 中用于生成文件头部正文和函数正文的插件
  • 文件头部增加正文

    • 在文件结尾增加正文,记录文件信息 / 文件的传参 / 出参等
    • 反对用户高度自定义正文选项, 适配各种需要和正文。
    • 保留文件的时候,自动更新最初的编辑工夫和编辑人
    • 快捷键:windowctrl+alt+imacctrl+cmd+ilinuxctrl+meta+i

  • 在光标处增加函数正文

    • 在光标处主动生成一个正文模板
    • 反对用户高度自定义正文选项
    • 快捷键:windowctrl+alt+t,macctrl+cmd+t,linux:ctrl+meta+t
    • 快捷键不可用很可能是被占用了,参考这里
    • 可自定义默认参数

  • Better Comments 通过应用警报,信息,TODO 等进行正文来改善代码正文。应用此扩大,您将可能将正文分类为:

    • 快讯
    • 查问
    • 待办事项
    • 强调
    • 正文掉的代码也能够设置款式,以使代码不应该存在
    • 可自定义指定其余所需的正文款式

  • TODO Highlight 突出显示 TODO,FIXME 和任何关键字

    • 高亮内置关键字,可通过自定义设置笼罩外观
    • 也可自定义关键字

用事实谈话

​ 口说无凭,眼见为实。上面咱们看下理论开发中的具体情况:

  • 没有正文
const noWarehousetemIds = beSelectSkucontainer.reduce((arr, itemId) => {const res = Object.keys(selectRowskey[itemId]).every((skuId) => {const sku = selectRowskey[itemId][skuId];
      return !!sku.warehouseCode || lodashGet(warehouses, '[0].code');
    });
    if (!res) {arr.push(itemId);
    }
    return arr;
  }, []);
  if (noWarehousetemIds.length > 0 || noStockItemIds.length > 0) {const itemIds = Array.from(new Set([...noWarehousetemIds, ...noStockItemIds]));
    const itemNames = itemIds.map(i => this.itemNameMap[i].itemName);
    return Modal.warning({
      title: '谬误提醒',
      content: `“${itemNames.join(',')}”库存信息未欠缺,请欠缺库存信息 `,
    });
  }
  • 个别般的正文
// 遍历以后所有选中的 sku,查找出没有库存的 itemId
const noStockItemIds = beSelectSkucontainer.reduce((arr, itemId) => {const res = Object.keys(selectRowskey[itemId]).every((skuId) => {const sku = selectRowskey[itemId][skuId];
    return !!sku.stockQuantity;
  });
  if (!res) {arr.push(itemId);
  }
  return arr;
}, []);
// 有一条 sku 的库存为空时进入校验
if (noStockItemIds.length > 0) {const itemNames = itemIds.map(i => this.itemNameMap[i].itemName);
  return Modal.warning({
    title: '谬误提醒',
    content: `“${itemNames.join(',')}”库存信息未欠缺,请欠缺库存信息 `,
  });
}
  • 更好的正文
// 遍历以后所有选中的 sku,查找出没有库存的 itemId
const noStockItemIds = beSelectSkucontainer.reduce((arr, itemId) => {
    // selectRowskey 是一个对象,以 itemId 为 key,sku 对象作为 value,sku 对象以 skuId 作为 key,sku 作为 value,只有 selectRowskey 下所有 itemId 下的 sku 都有库存才算校验通过
    /*
        数据格式:
        selectRowskey: {
          12345678: { // itemId
              123456: { // skuId
              name: 'sku',
              }
          }
        }
      */
    const res = Object.keys(selectRowskey[itemId]).every((skuId) => {const sku = selectRowskey[itemId][skuId];
        return !!sku.stockQuantity;
    });
    // 只有有一条 sku 没有库存时,就塞到 arr 中,返回给 noStockItemIds 数组
    if (!res) {arr.push(itemId);
    }
    return arr;
}, []);
// 有一条 sku 的库存为空时进入校验
if (noStockItemIds.length > 0) {
    // 依据 id 查找商品名称
    const itemNames = itemIds.map(i => this.itemNameMap[i].itemName);
    Modal.warning({
        title: '谬误提醒',
        content: `“${itemNames.join(',')}”库存信息未欠缺,请欠缺库存信息 `,
    });
}

​ 看到下面这段代码能够很显著的领会到有没有正文以及正文写的清不分明的重要性。若是写了正文但依然看不懂,那还不如不写。

​ 所以正文也不是轻易写一写就能够的,要形容某段代码的性能,注明逻辑,让开发者能够”无脑“浏览。

​ 之前在工作群中看到有人发过这样一张图(如下图),集体认为是一个很好的代码正文的范例:

结语

看到这里,对于正文的重要性各位曾经有本人的认知。还有几点是咱们写正文时须要留神的:

  • 正文内容要简洁、分明明了。正文简述性能或实现逻辑即可,无需每行代码都增加正文
  • 代码若有批改,切记同步批改对应的正文。不要呈现过期的正文,否则会起到副作用

    有任何意见欢送下方评论区留言探讨~

参考文献

  • 为什么要写正文
  • js/javascript 代码正文标准与示例
  • 代码中的非凡注解 — TODO、FIXME、XXX 的作用
  • 正文的作用, 以及如何写正文
  • 你确定 Java 正文不会被执行吗?80% 的人都不晓得。
  • IE 浏览器条件正文详解
  • 对于 CSS 中对 IE 条件正文的问题

招贤纳士

政采云前端团队(ZooTeam),一个年老富裕激情和创造力的前端团队,隶属于政采云产品研发部,Base 在风景如画的杭州。团队现有 40 余个前端小伙伴,平均年龄 27 岁,近 3 成是全栈工程师,妥妥的青年风暴团。成员形成既有来自于阿里、网易的“老”兵,也有浙大、中科大、杭电等校的应届新人。团队在日常的业务对接之外,还在物料体系、工程平台、搭建平台、性能体验、云端利用、数据分析及可视化等方向进行技术摸索和实战,推动并落地了一系列的外部技术产品,继续摸索前端技术体系的新边界。

如果你想扭转始终被事折腾,心愿开始能折腾事;如果你想扭转始终被告诫须要多些想法,却无从破局;如果你想扭转你有能力去做成那个后果,却不须要你;如果你想扭转你想做成的事须要一个团队去撑持,但没你带人的地位;如果你想扭转既定的节奏,将会是“5 年工作工夫 3 年工作教训”;如果你想扭转原本悟性不错,但总是有那一层窗户纸的含糊… 如果你置信置信的力量,置信平凡人能成就不凡事,置信能遇到更好的本人。如果你心愿参加到随着业务腾飞的过程,亲手推动一个有着深刻的业务了解、欠缺的技术体系、技术发明价值、影响力外溢的前端团队的成长历程,我感觉咱们该聊聊。任何工夫,等着你写点什么,发给 ZooTeam@cai-inc.com

退出移动版