对于代码的整体可维护性而言,注释是非常重要的一环。任何一个无注释的文件都是对后继者的折磨。适度的添加注释可以解释说明代码的来龙去脉,编程风格通常不会包含对注释的风格约定,但是 我认为在团队中,相同的注释风格可以减少误解和代码学习成本,同时也有利于做代码复盘
单行注释
独占一行的注释,用于解释下一行代码。这行解释之前总有一个空行 缩进层级和下一行代码保持一致
// good use
if (condition) {
// 如果代码执行到这里 则允许通过
allowed();
}
// bad use 注释之前没有空行
if (condition) {
// 如果代码执行到这里 则允许通过
allowed();
}
// bad use 注释没有正确的缩进
if (condition) {
// 如果代码执行到这里 则允许通过
allowed();
}
在代码行的尾部的注释 代码结束到注释之间应该至少有一个缩进。注释(包含之前的代码部分)不应当超过单行最大字符数限制,超出就将这条注释放置于当前代码行的上方
// good use
var result = something + somethingElse; // someThingElse不应当为null
// bad use 没有缩进
var result = something + somethingElse;// someThingElse不应当为null
单行注释不应当以连续多行注释的形式出现
// good use
// if (condition) {
// allowed();
// }
// bad use 这里应该使用多行注释
// 这段代码的实现逻辑:
// 1、***
// 2、**
// 3、*
if (condition) {
// 如果代码执行到这里 则允许通过
allowed();
}
推荐指数: 🌟🌟🌟🌟🌟
多行注释
多行注释可以包裹跨行文本。以/开始,以/结束。
合法注释示例
// legal comment usage
/* 我的注释 */
/* 另一段注释
这段注释包含两行*/
/*
又是一段注释
这段注释同样包含两行
*/
尽管从技术角度看,这些注释都是合法的 但是我更推荐java风格的多行注释。java风格的注释至少包含三行: 第一行是/,第二行是以开始且和上一行的保持左对齐,最后一行是/。like this
// java style
/*
* 另一段注释
* 这段注释包含两行文本
*/
多行注释总会出现在将要描述的代码段之前,注释和代码之间没有空行间隔和单行注释一样,多行注释之前应该有一个空行,且缩进层级和其描述代码应该保持一致
// good use
if (condition) {
/*
* 如果代码执行到这里
* 说明通过了所有的安全监测
*/
allowed();
}
// bad use 没有空行
if (condition) {
/*
* 如果代码执行到这里
* 说明通过了所有的安全监测
*/
allowed();
}
// bad use 星号之后没有空格
if (condition) {
/*
*如果代码执行到这里
*说明通过了所有的安全监测
*/
allowed();
}
// bad use 错误的缩进
if (condition) {
/*
* 如果代码执行到这里
* 说明通过了所有的安全监测
*/
allowed();
}
// bad use 代码尾部注释不应该使用多行注释格式
var result = something + somethingElse; /*something 不能是null*/
推荐指数: 🌟🌟🌟🌟🌟
使用注释
何时添加注释是程序员经常争论的一个话题。通用的指导原则是,当代码不够清晰时添加注释,代码足够简单明了时不应当添加注释
// bad use
// 初始化count
var count = 10;
如果count是个特殊的变量 可以将用途或者影响到的元素注释进来,初始化是显而易见的,没有任何价值
// good use
// 这个值更改后 会对金额总计 金额小计 应收金额字段进行重新计算
var count = 10
注释中给了必要信息,没有注释,其他维护人员或者参考此处代码人员需要去查找梳理逻辑,因此添加注释的一般原则是,在需要让代码变得更清晰时添加注释
推荐指数: 🌟🌟🌟🌟🌟
难以理解的代码
难以理解的代码,通常都应该加注释。根据代码的用途,你可以添加单行注释、多行注释。或者混用两种注释。关键是让其他人更容易读懂这段代码。like this 代码摘自于 YUI类库的Y.mix()方法
// good use
if (mode) {
/*
* 当mode为2时(原型到原型,对象到对象),这里只递归一次
* 用来执行原型到原型的合并操作,对象到对象的合并操作
*/
if (mode == 2) {
Y.mix(r.prototype, s.prototype, ov, wh, 0, merge)
}
...
/*
* 如果 supplier或receiver不包含原型属性的时候
* 则逻辑结束并返回Unfeined, 如果有原型属性
* 返回 receiver
*/
if (!from || !to) {
return receiver;
}
}
如果不写注释,仅通过这些数值无法理解各自代表的含义。这里的注释可以及时地解释这里的复杂逻辑
可能被认为错误的代码
while (element && (element = element[axis])) { // 提示:赋值操作
if ( (all || element[TAG_NAME]) && (!fn || fn(element)) ) {
return element;
}
}
在这个例子里面,开发者在while循环控制条件中使用了一个赋值运算符。这不是一个常规的标准做法,常常会被检测工具认为是有问题的。很可能会被误认为是一个错误,如果作者在这里加了注释,证明是有意为之,这样其他人在读到的时候,不会认为是个错误就不会将其修复。
浏览器特性hack
js程序中常常会编写一些低效的,不雅的,彻头彻尾的脏代码,用以支持低级浏览器正常工作。这种代码,因为做了浏览器特性hack,可能会隐含一些错误
var ret = false;
if (!needle || !element || !needle[NODE_TYPE] || !element[NODE_TYPE]) {
ret = false;
} else if (element[CONTAINS]) {
// 如果needle不是ELEMENT_NODE时,IE和Safari下会有错误
if (Y.UA.opera || needle[NODE_TYPE] === 1) {
ret = element[CONTAINS](needle)
...
} else {
...
}
}
这行代码很关键,IE和Safari都有内置方法contains(),但如果needle不是一个元素的时候,这个方法会报错,所以只有当浏览器是Opera时才可以采用这个方法,其他浏览器中needle必须是 一个元素(nodeType是1)。这里关于浏览器的说明同样解释了为什么需要一个if语句,这个注释不仅确保将来不会被误改动,而且也有利于,编写者在回头阅读该代码时,可以适时针对新版本IE和Safari进行兼容调整
推荐指数: 🌟🌟🌟🌟
文档注释
文档注释,目前最流行的一种格式来自于JavaDoc文档格式:多行注释以单斜线加双星号(/**)开始,接下来是描述信息,其中以@符号来表示一个或者多个属性,以下是我个人建议,规范常用的代码片段
// good use: 变量
/*
* 一个字符或者数字的变量
* @type {(string|number)}
*/
var val;
// good use 函数: 传入的是单个变量
/*
* 这个函数的作用的简单汇总
* @param {number} a 变量描述
* @param {string} b - 或者加上连字符便于阅读
* @param {string} c - 这个参数有很长很长很长
* 很长的描述
*/
function myFun(a, b, c) {
}
// good use 函数: 传入的参数是对象
/*
* 这个函数的作用的简单汇总
* @param {object} options - 传入的对象参数
* @param {string} options.name - 对象的name属性
* 属性的解释
* @param {number} options.age - 对象的age属性
* 很长的描述
*/
function myFun(options) {
}
// good use 函数: 传入的参数是数组
/*
* 任意多个参数的函数
* 返回所有传入的参数和
* @param {...number} nums - 参数个数任意,都是数字属性
*/
function sum(nums) {
}
// good use 函数:有返回值和描述
/*
* 返回两个数之和
* @description 描述使用场景等
* @param {number} a - 数字
* @param {number} b - 数字
* @returns {number} 数字之和
*/
function sum(a, b) {
return a + b;
}
- // TODO功能未完成,待完善
- // FIXME 待修复
- // XXX 实现方法待确认
- // NOTE 代码功能说明
- // HACK 此处写法有待优化
- // BUG 此处有 Bug
/*
* ...
* NOTE: 这里只是个测试用例函数
* FIXME: 举个栗子
* TODO: ...
*/
function fnExample(a, b) {
...
}
推荐指数: 🌟🌟🌟🌟🌟🌟