写在文章前
这篇文章翻译自13 Noteworthy Points from Google’s JavaScript Style Guide . 如果觉得风格指南的完整版太长的话,这篇文章提取出来了比较值得注意的几点,比如说tab vs space这种堪比咸甜豆腐脑的战争。(还记得美剧硅谷中,Richard就因为是坚定地‘tab键’党跟女友分了手。文章翻译的不好的地方还望指出和多多包涵。
Google的javascript风格指南中值得注意的13点
众所周知,GOOGLE推出了一个针对如何写JavaScript的风格指南,这个指南被认为(Google 自己认为)是能够写出整洁,易理解代码的最佳风格化实践。
这些不是针对如何编写严谨的JavaScript代码的那种严格和快速的规则, 仅仅只是一些为了保持原文件中一致,和保证吸引人的风格选择而提出的一些禁止行为。这对于JavaScript来说是格外有趣的,因为JavaScript是一个灵活的,“宽容的”语言,它总是允许广泛的不同的风格化选择。
Google 和 Airbnb 拥有两种最流行的风格指南。我强烈的建议你们两套指南都去看一看,如果你花大量时间写JS代码。
下面的十三条是我认为在Google Js 风格指南中最有趣和最相关的规则。
这些规则处理了那些引起人们激烈竞争的问题(比如说tab vs 空格键, 如何使用分号的争议),以及更多的处理了一些模糊的规则,这让我很惊喜。他们无疑会改变我以后写我的js代码的方式。
对于每一个规则, 我会写一个规则总结,跟着一个在风格指南中详细描述这条规则的支持引用的后面。如果可行,我也会提供一个这种书写风格在实际中的例子,并把它与不遵从这种规则的代码进行对比。
使用空格,而不是tab键
Aside from the line terminator sequence, the ASCII horizontal space character (0x20) is the only whitespace character that appears anywhere in a source file. This implies that… Tab characters are not used for indentation.
除行终结符外,ASCII水平空格字符(0x20)是出现在源文件中各处的唯一的空白格字符,这表明......(此处省略)......Tab字符不应该被用于缩进
这条指南指出你应该使用两个空白格(而不是四个)来缩进。
//译者注:'.'代表空格
//bad
function foo(){
....let name;
}
//bad
function bar(){
.let name;
}
//good
function baz(){
..let name;
}
复制代码
分号应该加
Every statement must be terminated with a semicolon. Relying on automatic semicolon insertion is forbidden. 每一个声明必须要以分号结尾。严禁完全依赖自动分号注入机制;
尽管我难以想象为什么每个都反对这个想法,但在js中贯彻分号的使用已经变成了新的‘空格 vs tab’斗争。 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模块( 以目前的状况来看)
Do not use ES6 modules yet (i.e. the export and import keywords), as their semantics are not yet finalized. Note that this policy will be revisited once the semantics are fully-standard. 目前,不要使用ES6 模块(例如,关键字export和import相关),因为他们的语义并没被完善,注意,一旦es6的语义被完全标准化,这条政策就会被重新审查。
//不要写下面这种做法
// ------- 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';
复制代码
不建议使用水平对齐(但不禁止)
This practice is permitted, but it is generally discouraged by Google Style. It is not even required to maintain horizontal alignment in places where it was already used. 水平对齐这种做法是允许的,但他不是Google风格所提倡的。在那些已经用到水平对齐的地方,甚至不需要继续维持水平对齐。
水平对齐是一种在你的代码中增加许多不同数量的额外空格的做法,目的是为了让某种符号直接出现在之前的某些行的某些符号下方。
//bad
{
tiny: 42,
longer: 435,
}
//good
{
tiny: 42,
longer: 435,
}
复制代码
不要再使用var关键字了
Declare all local variables with either const or let. Use const by default, unless a variable needs to be reassigned. The var keyword must not be used. 使用const或者let 来声明所有的局部变量。默认情况下使用const关键字,除非需要重新分配一个变量。
var
关键字请不要使用。
我仍旧在StackOverFlow或者其他地方的代码片段中看到某些人还在使用var
。我不能确定是否这些人在真正的代码中会转化成const或者换var,还是这只是一些很难完全改掉的旧习惯。
// bad
var example = 42;
// good
let example = 42;
复制代码
优先使用箭头函数
箭头函数提供给我们一种简洁的语法并且修复了许多由于this指针导致麻烦。优先在函数关键字中使用箭头函数,尤其是那些嵌套函数。
说实话,我只是因为箭头函数更简洁和看起来更好看而觉得箭头函数很好。事实上,他们提供了一个更重要的理由去使用箭头函数。
//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;
})
复制代码
使用模板字符串来代替数组合并
Use template strings (delimited with `)over complex string concatenation, particularly if multiple string literals are involved. Template strings may span multiple lines. 使用模板字符串来进行复杂字符串的连接(用 ` 分割),尤其是有大量字符串文字的情况。模板字符串可以跨越多行。
//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}?`;
}
复制代码
不要对长字符串使用续行符号
Do not use line continuations (that is, ending a line inside a string literal with a backslash) in either ordinary or template string literals. Even though ES5 allows this, it can lead to tricky errors if any trailing whitespace comes after the slash, and is less obvious to readers. 无论在普通字符串或者模板字符串中都不要使用续行符(续行符就是使用反斜杠的字符串结束一行)。 尽管ES5允许这么做,但是如果在反斜杠之后有空格尾随就会导致非常意料之外的错误,并且对于阅读的人来说不明显。
非常有趣的是,有关于这一条,Google和airbnb都不同意使用续航符号。
Google建议拼接尽可能长的字符串(例子在下面)。Airbnb风格指南事实上建议什么都不做,并且允许字符串可以是任何它需要的长度。
//bad (sorry, this doesn`t show up well on mobile)
const longString = 'This is a very long string that \
far exceeds the 80 colomn 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循环的首选类型
With ES6, the language now has three different kinds of for loops. All may be used, though for-of loops should be preferred when possible. 在ES6中,JS语言现在有三种不同种类的for循环。三种都能被使用,但是for-of循环在可以使用的时候应该被优先选择。
如果你问我的话,我会觉得这条很奇怪,但我认为,我应该把这条涵盖进来因为google声明了一种喜爱的for循环形式是十分有趣的。
在我看来,for...in
循环更适合遍历object对象,而for..of
循环更适合数组。毕竟杀鸡焉用宰牛刀?
虽然Google对于这条的声明并没有完全反驳我的观点,但是知道他们对于for循环的偏好依旧是一件非常有趣的事情。
不要使用eval()##
Do not use eval or the Function(...string) constructor (except for code loaders). These features are potentially dangerous and simply do not work in CSP environments. 不要使用eval 或者 Function(...string) 构造器(除非是代码加载器)。这些特点是一些潜在的危险,并且很容易在CSP环境中无法运行。
MDN 官网对于eval()
甚至有一个小节叫做'不要使用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"] 和obj.a是一样
复制代码
常量应该被以全大写的方式并使用下划线分隔得方式命名(ALL_UPPERCASE)
Constant names use CONSTANT_CASE: all uppercase letters, with words separated by underscores. 常量应该使用常量格式(CONSTANT_CASE): 全部使用大写字母,并使用下划线进行单词分隔。
如果你十分的确定一个变量不会被改变,那你应该以全大写名字的方式声明这个常量。这会使常量的不变性更明显的贯彻在你的代码中。
一个需要注意的使用这个规则例外就是如果常量是函数作用域内的情况。在这种情况下,常量要被写为驼峰式。
// bad
const number = 5;
// good
const NUMBER = 5;
复制代码
一个声明, 一个变量
Every local variable declaration declares only one variable: declarations such as let a = 1, b = 2; are not used. 一个局部变量只声明一个变量:形如 let a = 1 , b = 2 这种声明方式不应被使用。
//bad
let a = 1, b = 2, c = 3;
//good
let a = 1;
let b = 2;
let c = 3;
复制代码
使用单引号,不要使用双引号
Ordinary string literals are delimited with single quotes ('), rather than double quotes ("). 普通的字符串使用单引号(')分隔,不建议使用双引号(").
建议: 如果一个字符串中包括单引号字符,使用模板字符串来避免转义引号。
//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这样拥有众多写得出优秀代码的优秀程序员的大公司推出了这样一套样式建议是十分有趣的。
如果你想写出‘google 兼容的源码’,你可以遵从这些规则,但是,显然,有很多人并不同意这些规则。已完全可以为所欲为的违反一个甚至所有的规定。
我个人认为,airbnb的规定比Google的更吸引人。但无论你对这些规定采取什么态度和立场,重要的是要时刻保持代码样式风格的一致性。
译者结语
在原文作者的评论中,我个人觉得有一个评论特别有道理。这种样式风格其实针对团队更多一些。因为个人的习惯基本不会有太大的变化,很不容易在代码中存在风格不一致,但是当团队完成工作的时候,很容易会出现风格冲突的问题。这样的代码不利于维护和阅读,有的时候可能还会有更糟的情况比如变量污染等问题。 因此制定一个规范可以很好的解决问题,无论遵从的google的,airbnb的或者你所在的团队自己的。