美文网首页
关于javascript的一些规范

关于javascript的一些规范

作者: AmazRan | 来源:发表于2019-06-22 23:52 被阅读0次

前言

阅读谷歌的js规范后一些心得与归纳总结,除此之外还记录部分日常js使用该注意的点


基础规范

  1. 文件命名 按照项目的风格习惯命名,必须小写,可以包含下划线_和分隔符-
  2. UTF-8格式编码
  3. 所用空格字符都需要被转义为空格,tab不该被使用
  4. 使用特殊转移句型\', \", \\, \b, \f, \n, \r, \t, \v而不是转义后的例如\x0a, \u000a, or \u{a}
  5. 不带入ASCII字符或其他转,让代码更易阅读和理解

源文件结构

按照以下顺序构成:

  1. 证书或授权信息(若存在)
  2. JSDoc,文件的总体概要
Example:
/**
 * @fileoverview Description of file, its uses and information
 * about its dependencies.
 * @package
 */
  1. 模块声明
  2. 模块引入
    已引入的模块禁止再引入其子模块
    不能被包裹,必须在顶部
  3. 文件实现 即code部分内容

格式化

括号Braces

逻辑结构(例如if, else, for, do, while等)必须包裹括号
可保持单行且不影响可读性时例外:if (shortCondition()) return;
没有空格(K&R style)
{ 前不能换行后要换行
} 前要换行,如果代表着判断(如if)结束则换行
空内容则闭合

// 合法:
function doNothing() {}
// 非法:
if (condition) {
  // …
} else if (otherCondition) {} else {
  // …
}
try {
  // …
} catch (e) {}

缩进使用2个空格
状态:每条状态独立一行且必须跟分号,依靠自动补全分号是禁止的🚫
一行限制少于80个字符
换行,没有特定的公式约束,
tips:可以拆分出方法或本地变量减少长度不必换行

// 鼓励
currentEstimate =
    calc(currentEstimate + x * currentEstimate) /
        2.0f;
// 不鼓励
currentEstimate = calc(currentEstimate + x *
    currentEstimate) / 2.0f;
空格间隙
  1. 垂直回车:在一个类或对象文字之间的连续方法,多个回车不推荐使用但允许。方法内部首尾禁止空行。
  2. if、for、catch后的( 之间加空格
    else、catch前的} 之间加空格
    任意 { 前除了①foo({a: [{c: d}]})方法或array的首个参数②${}模板语言
    运算符前后加空格
    : 之后加空格
    js注释// 后或者/* 之间 */
  3. 不建议空格用于水平对齐(例如变量命名长度不一样强制让等号同一垂直线)
  4. 函数过长时,缩进4个空格换行提高可读性
doSomething(
    veryDescriptiveArgumentNumberOne,
    veryDescriptiveArgumentTwo,
    tableModelEventHandlerProxy,
    artichokeDescriptorAdapterIterator) {
  // …
}

语法特征

1. 变量声明
  • 默认使用const,需要重新赋值时才用let,禁止使用var
  • 一次声明一个变量let a = 1, b = 2不被允许
  • 用到时声明变量,尽可能缩小其作用域,而不是在块级结构的开头声明
  • 如果需要备注类型,例如可以知道该array将来用来装什么参数
const /** !Array<number> */ data = [];
/** @type {!Array<number>} */
const data = [];
2. 数组
  • 用逗号结尾换行分割
  • 不使用Array构造数组,不使用const a1 = new Array(x1, x2, x3)
    而是const a1 = [x1, x2, x3]
    若明确知道其长度则可以使用new Array(length)
  • 不要在array上定义或使用非数字属性(length除外)
  • 使用扩展符
[...foo]   // preferred over Array.prototype.slice.call(foo)
[...foo, ...bar]   // preferred over foo.concat(bar)
3. Object
  • 属性后面永远跟逗号不管是否为最后一条
  • 不使用Object构造器构建对象。即便没有Array的问题,为了一致性依然不建议这么做。使用({} or {a: 0, b: 1, c: 2})
  • 不混合使用引用和非引用key,即统一加或不加引号
  • 可以使用混合属性名
  • 方法可以缩写method() {… }
  • 缩写属性是可以被接受的
const foo = 1;
const bar = 2;
const obj = {
  foo,
  bar,
  method() { return this.foo + this.bar; },
};
  • 枚举应该注释@enum 告诉可以添加的数据类型
/**
 * Supported temperature scales.
 * @enum {string}
 */
const TemperatureScale = {
  CELSIUS: 'celsius',
  FAHRENHEIT: 'fahrenheit',
};
/**
 * An enum with two options.
 * @enum {number}
 */
const Option = {
  /** The option used shall have been the first. */
  FIRST_OPTION: 1,
  /** The second among two options. */
  SECOND_OPTION: 2,
};
4. Classes
  • 构造函数是可选项,子类必须先调用super()
  • 私有字段后面带_ 且注释@private
  • 复合属性只有symbol可以使用
  • 不要直接操作prototype(框架代码、定义接口中字段除外)
  • 不要使用Js的getter、setter(数据绑定类框架除外)
  • 可以重写toString方法但是必须成功且不能有可预见的错误
  • 接口必须备注@interface 或 @record.
5. Functions
  • 箭头函数解决了一堆this问题,更倾向于使用,尤其是子类函数。尽量避免去书写self = this。写括号是个好习惯即使只传入1个参数。
  • 生成器function后带*再接上空格和方法名。*跟随yield
/** @return {!Iterator<number>} */
function* gen1() {
  yield 42;
}
/** @return {!Iterator<number>} */
const gen2 = function*() {
  yield* gen1();
}
class SomeClass {
  /** @return {!Iterator<number>} */
  * gen() {
    yield 42;
  }
}
  • 参数名。传入的参数名必须带有注释@param
  • 返回Returns。必须注释返回类型
6. 字符
  • 使用单引号
  • 使用模板字符。如果产生换行,不需要保持缩进
function arithmetic(a, b) {
  return `Here is a table of arithmetic operations:
${a} + ${b} = ${a + b}
${a} - ${b} = ${a - b}
${a} * ${b} = ${a * b}
${a} / ${b} = ${a / b}`;
}
  • 不使用\ 行延续符
7. 控制结构语句
  • 三种for都可以使用,更加推荐for-of。尽量用Object.keys和for-of代替for-in。使用Object.prototype.hasOwnProperty来排除for-in遍历时取到的原型属性。
  • 遇到异常永远new Error抛出异常,永远不要抛出字符或其他格式。极少数情况抛出异常算为正常执行无需做处理一定要备注。
  • switch在不调用break时需备注// fall through,最后一个状态块不需要,即使没有代码也要写default。
8. this
  • 只在class构造函数和方法或者是这两个中定义的箭头函数中可以使用。其他地方必须有个显示的备注告诉this指向。
  • 永远不要用this指向 the global object, the context of an eval, the target of an event, or unnecessarily call()ed or apply()ed functions
9. 禁止使用
  • with 🚫
  • 动态词法解析🚫。eval或者是Function(...string) constructor(code loader 除外)
  • 自动插入分号🚫。永远手动末尾写分号(function class声明除外)
  • 非标准的一些特征🚫
  • 在原始类型外包裹了一层object,永远不要对Boolean, Number, String, Symbol使用new
// 非法
const /** Boolean */ x = new Boolean(false);
if (x) alert(typeof x);  // alerts 'object' - WAT?
// The wrappers may be called as functions for coercing
// (which is preferred over using + or concatenating the empty string)
// or creating symbols.

// 合法
const /** boolean */ x = Boolean(0);
if (!x) alert(typeof x);  // alerts 'boolean', as expected
  • 不在全局对象上加symbol除非非常有必要

命名

使用字符或数字命名,少数情况下会去使用$_(例如Angular中)
尽可能的给变量名一个文字描述,不要担心敲多余的空格,让别人一眼就能看懂你的代码比这重要得多。不要写一些其他人看不懂的缩写。

// legal
priceCountReader      // No abbreviation.
numErrors             // "num" is a widespread convention.
numDnsConnections     // Most people know what "DNS" stands for.
// Illegal:
n                     // Meaningless.
nErr                  // Ambiguous abbreviation.
nCompConns            // Ambiguous abbreviation.
wgcConnections        // Only your group knows what this stands for.
pcReader              // Lots of things can be abbreviated "pc".
cstmrId               // Deletes internal letters.
kSecondsPerDay        // Do not use Hungarian notation.

根据类型命名

  1. 包:小写驼峰(例如my.exampleCode
  2. class:大写驼峰(例如ImmutableList
  3. 方法:小写驼峰。动词形式sendMessage or stop_,私有方法后面接下划线_
  4. 枚举:大写驼峰
  5. 常量名:大写下划线分割_。CONSTANT_CASE 当需要本地重命名时,保留最后一部分且一定使用const
    例如const CONSTANT_NAME = ImportedClass.CONSTANT_NAME;
  6. 非常量字段名:小写驼峰,私有接下划线_
  7. 参数名:小写驼峰
  8. 本地变量名:小写驼峰

引申内容

关于是否句末要写分号?
google规范说法是必须写分号,不使用自动添加分号的工具
从今天的角度讲,很多团队倾向于不写分号,认为是一种语法噪音。

首先思考Javascript自动补全分号的规则是什么?

  • 要有换行符,且下一个符号是不符合语法的,那么就尝试插入分号。
  • 有换行符,且语法中规定此处不能有换行符,那么就自动插入分号。
  • 源代码结束处,不能形成完整的脚本或者模块结构,那么就自动插入分号。
// 通过这个实际例子去分析可以更清楚。两个立即执行函数表达式(IIFE),
// 第一个函数JavaScript引擎认为是返回的可能是个函数,所以不会自动插入分号
// 这是一些鼓励不写分号的编码风格会要求大家写 IIFE 时必须在行首加分号的原因。
(function(a){
    console.log(a);
})()
(function(a){
    console.log(a);
})()

关于Javascript自动补全分号机制和no line terminator的规则,不在本篇做过多分析,仅仅是证明了不写分号的确存在一些导致语句执行发生问题的风险。所以也存在了通过eslint fix去补全规避风险。
个人认为谷歌提倡的规范更加具有主动性,有很大的借鉴意义。


心得总结

google的规范写的很详细且有在更新维护。日常开发团队如果没有严格要求,不妨作为规范来参考,并不一定完全要照着做但是许多开发中的良好习惯养成了,肯定没有坏处!


参考

谷歌css/js规范

相关文章

网友评论

      本文标题:关于javascript的一些规范

      本文链接:https://www.haomeiwen.com/subject/xfoxqctx.html