[译] Google JavaScript 风格指南中 13 个值得注意的细节

2,704 阅读7分钟

图片描述

原文地址:13 Noteworthy Points from Google’s JavaScript Style Guide
原文作者:Daniel Simmons
译者:命名最头疼

对编码风格不熟悉的人而言,Google 推出一套用于编写 JavaScript 代码的样式指南, 并指出(谷歌认为)编写清晰易懂的代码最佳风格。

首先声明一点,以下规则并不是编写 Javascript 代码的硬性要求,仅是为了维持项目代码的一致性,Javascript 是一种灵活而宽松的语言,它允许各种风格。

Google 和 Airbnb 都推出了各自的编码风格指南,且是比较受欢迎的,如果你的项目中需要编写大量的JS代码,我绝对建议你阅读。

以下列出了在 Google JS 风格指南中我认为比较有趣且实用的 13 条规则

Google对编码中的每个细节点都进行了争议(标签, 空格,以及分号的使用)还有一些模糊的规范, 无疑, 这套风格肯定会改变我写JS的方式。

对每一条规则,我都会列出规范的摘要部分,然后是样式指南中的支持引用和详细描述规则,在恰当的情况下,我将举例说明,并与之和不遵循规则的代码进行对比。

推荐使用空格, 而不是tab键

除了行终止符以外,ASCII 中的水平空格字符 (0x20) 是唯一一个表示空格的空白字符,这意味着 Tab 键并不适用于缩进。

  // bad
    function foo() {
    ∙∙∙∙let name;
    }

    // bad
    function bar() {
    ∙let name;
    }

    // good
    function baz() {
    ∙∙let name;
    }

推荐使用分号, 而不是将其省略

每条语句结束后必须带有分号,严禁依赖编译器自动插入分号。 虽然我无法想象为什么有人会反对这个想法,但是 JS 中一贯使用分号将成为新 "spaces versus tabs" 争论,Google 表示坚持分号的使用。

  // bad
  let luke = {}
  let leia = {}
  [luke, leia].forEach(jedi => jedi.father = 'vader')
  // good
  let luke = {};
  let leia = {};
  [luke, leia].forEach((jedi) => {
    jedi.father = 'vader';
  });

不要使用 ES6 模块

不要使用 ES6 模块(即 export 和 import 关键词),因为它们的语义尚未最终确定,注意,一旦语义完全标准化,将重新审视这条规则。

// 现在先不要这样用:
//------ lib.js ------
export function square(x) {
    return x * x;
}
export function diag(x, y) {
    return sqrt(square(x) + square(y));
}

//------ main.js ------
import { square, diag } from 'lib';

不推荐水平对齐(但不禁止)

首先水平对齐这种做法是允许的,但是在 Google 风格中并不推荐这种用法。甚至不需要在已使用过的地方保持水平对齐。 水平对齐即在代码中添加空格,使每一列对齐。

// bad
{
  tiny:   42,  
  longer: 435, 
};
// good
{
  tiny: 42, 
  longer: 435,
};

不要再使用var

使用 const 或 let 声明所有局部变量,除非需要重新分配变量,否则默认使用 const,不推荐使用 var 关键词。 我仍然看见人们在 StackOverflow 和其他地方使用 var 代码示例。可能有人会为此反对,或者说这是一种旧习惯,要改变,比较困难。

// bad
var example = 42;
// good
let example = 42;

首选箭头函数 箭头函数提供一个简洁的句法,并解决了许多困难,首选箭头函数而不是函数关键词,尤其是嵌套函数 说句真心话,我认为箭头函数非常棒,因为他们更加简洁,更好看,事实证明,他们也有很重要的作用。

// bad
[1, 2, 3].map(function (x) {
  const y = x + 1;
  return x * y;
});

// good
[1, 2, 3].map((x) => {
  const y = x + 1;
  return x * y;
});

使用模板字符串代替连接符

在复杂字符串上使用模板字符串 (``) 而是不是连接符 (+) ,特别是涉及多个字符串文字的情况下,模板字符串可以跨行

// bad
function sayHi(name) {
  return 'How are you, ' + name + '?';
}

// bad
function sayHi(name) {
  return ['How are you, ', name, '?'].join();
}

// bad
function sayHi(name) {
  return `How are you, ${ name }?`;
}

// good
function sayHi(name) {
  return `How are you, ${name}?`;
}

对长字符串不要使用行连续符

不要在普通字符串或模板字符串中使用行连续(即, 通过反斜杠结束字符串文字内的一行)尽管 ES5 允许这样做,如果有空格尾随在后面,它将会导致棘手的错误,并且对读者来说不那么明显。

有趣的是,Google 和 Airbnb 都不赞同这种做法这又Airbnb规范

谷歌的建议是通过连接符来拆分长字符串(如下所示),而 Airbnb 则建议写成一行,允许出现长字符串(如果需要的话)

// bad (sorry, this doesn't show up well on mobile)
const longString = 'This is a very long string that \
    far exceeds the 80 column limit. It unfortunately \
    contains long stretches of spaces due to how the \
    continued lines are indented.';
// good
const longString = 'This is a very long string that ' + 
    'far exceeds the 80 column limit. It does not contain ' + 
    'long stretches of spaces since the concatenated ' +
    'strings are cleaner.';

for...of是for循环首选

ES6 提供了三种不同的 for 循环。三个可用情况下,如果可以, 推荐优先使用 for-of 循环

包括我在内, 也觉得这条规则有点奇怪,但是谷歌认为它作为 for 循环的首选将会非常优雅

我认为,for...in 循环更适合对象,而 for...of 更适合数组

虽然 Google 的规范并不一定能和我们想法相吻合, 但是它依旧觉得这种做法相当优雅

不要使用eval()

不要使用 eval 或 Function(...String) 构造函数(代码加载器除外),这些功能具有潜在风险,并且在 CSP 环境中无法正常工作。

对于 eval() 而言,在 MDN 页面甚至专门有一页去呼吁不要使用 eval()

// bad
let obj = { a: 20, b: 30 };
let propName = getPropName();  // returns "a" or "b"
eval( 'var result = obj.' + propName );
// good
let obj = { a: 20, b: 30 };
let propName = getPropName();  // returns "a" or "b"
let result = obj[ propName ];  //  obj[ "a" ] is the same as obj.a

常量应该用大写字母和下划线表示

常量名称使用 CONSTANT_CASE: 全部为大写字母,单词用下划线分割。

如果你能确保一个变量不会再改变,你可以通过大写常量的名称来表明这一点,这使得常量的不变性在整个代码的使用中显而易见。

这个规则有个值得注意的例外是,如果常量是属于函数范围的,在这种情况下,应该将其用驼峰命名法来表示。

// bad
const number = 5;
// good
const NUMBER = 5;

每次只声明一个变量

每个局部声明只声明一个变量,例如 let a = 1, b = 2 是不被允许的。

// bad
let a = 1, b = 2, c = 3;
// good
let a = 1;
let b = 2;
let c = 3;

使用单引号而不是双引号

普通的字符文本使用单引号(')来分割,而不是双引号(")

Tip: 如果一个字符串文本中包含单引号字符,请考虑使用模板字符串,而避免使用转义符号。

// bad
let directive = "No identification of self or mission."
// bad
let saying = 'Say it ain\u0027t so.';
// good
let directive = 'No identification of self or mission.';
// good
let saying = `Say it ain't so`;

最后一点 正如我一开始说的那样,以上这些规则并不是强制性的,Google 只是众多科技巨头中的一员,这些只是建议。

也就是说,看看像谷歌这样的公司提出的风格建议很有意思,它聘请了许多精彩的人,他们花了很多时间去编写优秀的代码。

如果你想遵循 “ Google 标准源码 ” 指南,你可以遵循这些规则,当然,很多人不同意,你可以部分遵循,甚至不遵循也可以。

我个人认为,很多情况下 Airbnb 比 Google 的规范更具吸引力,无论在何种情况下,一定要牢记,整个项目的编码风格要保持统一。