编者按:谷歌的程序员大大为了帮助刚入手JavaScript的小白们写出干净、易懂的代码,提供了一个独具特色的教程《Java Script指南》,而本文作者丹尼尔西蒙斯,一位web开发人员/Java爱好者精心总结了谷歌推出的这份指南中最有趣、最有用的十三条规则。
JS具有强大的灵活性和包容性,因此,JS的编写具有不同的风格,因此如何保证你的源程序在编写过程中保持着统一的风格才是编写JS的过程中需要注意的。
谷歌和Airbnb使用着两种最流行的编写规则,它们对细节的把控深深的影响着我,从一个个的标点到页面的布局,扣着一个个的小细节,这也深深的影响了我在码JS过程中的一些习惯。以下是我挑选的谷歌JS指南中最有趣、有用的十三条规则。
我将针对每一个规则都会给一个总体的叙述,然后再进行详细的叙述,结合自身的开发经历,给出一些实用的介绍,如果条件允许,还有一些相关的例子给大家分享一下。
除了行终止符之外,ASCII字符(0x20)是在源文件中出现的唯一空白字符。这意味着Tab制表符不用于缩进。
因此,你应该使用空格来实现你的设计而不是Tab制表符,而且只要键入两个空格就可以,而不是四个空格。
// bad function foo() { ∙∙∙∙let name; } // bad function bar() { ∙let name; } // good function baz() { ∙∙let name; }
每个语句都必须以分号结束。不要为了省事使用自动分号插入。那会给你带来后面很多不必要的麻烦的。
// bad let luke = {} let leia = {} [luke, leia].forEach(jedi => jedi.father = ‘vader’)// good let luke = {}; let leia = {}; [luke, leia].forEach((jedi) => { jedi.father = ‘vader’; });
虽然我无法想象为什么有人反对这个想法,但在JS中使用分号正在成为一种新的“空格与制表符”的争论。谷歌是支持使用分号的,至于刚入行的小白还是建议跟着潮流走。
不要使用ES6模块(即导出和输入关键字),因为它们的语义还没有最终确定。
// Don’t do this kind of thing yet: //—— 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’;
在谷歌提供的模板里面,水平对齐并没有提出很高的要求,还是比较随意的。
水平对齐就是在目标模块的周边增加可变数量的额外空格,使得目标出现在我们想让他出现的位置上就可以。
// bad { tiny: 42, longer: 435, };// good { tiny: 42, longer: 435, };
除非需要重新分配一个变量,否则将所有本地变量声明为const关键字或let型。默认情况下使用const。但是在使用var关键字的时候一定要慎重。
其实在平时学习中,我仍然看到人们在StackOverflow和其他地方的代码示例中使用var型。我不知道其他人使用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允许这样做,但如果在斜杠之后出现任何尾随空格,那么它就会导致棘手的错误,而且对新手来说不太明显。
// 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.’;
有趣的是,这是谷歌和Airbnb意见不同的规则(这是Airbnb的规范)。虽然谷歌推荐连接更长的字符串(如下所示),但Airbnb的风格指南建议基本上什么都不做,并且允许长字符串在需要的时候继续使用。
在ES6中,语言现在有三种不同的for循环。程序员是可以使用所有的循环,但在可能的情况下应该首选for-of循环。
我个人感觉for更适合于对象,而for of更适合于数组。只是适合不同的风格。虽然谷歌的规范并不一定与这个想法相矛盾,但是,可以看出谷歌对于这个循环还是情有独钟的。
不要使用eval或函数(…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 let a = 1, b = 2, c = 3;// good let a = 1; let b = 2; let c = 3;
普通的字符串是用单引号(‘)来分隔的,而不是双引号(“)。
提示:如果字符串包含单引号字符,请考虑使用模板字符串,以避免误导。
// 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`;
正如我一开始所说的,这些不是唯一的标准。谷歌只是众多科技巨头中的一个,而这些只是众多程序员总结出来的经验而已。
看看谷歌这样的公司提出的风格建议还是比较有意义的,它雇佣了很多聪明的人,他们花了大量时间研究如何编写优秀的代码。
如果你想遵循“谷歌兼容的源代码”的指导方针,你可以遵循这些规则——但是,你要是有自己的喜好,那很棒,你可以自由地放飞自我。
我个人认为,在很多情况下,Airbnb的规范比谷歌更有吸引力。不过无论对这些特定的规则采取何种立场,我们在编写任何类型的代码时,唯一的要求就是要保持风格上的一致性。