You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// badfunctionprocessInput(input){// then a miracle occursreturn[left,right,top,bottom];}// 调用时需要考虑回调数据的顺序。const[left,__,top]=processInput(input);// goodfunctionprocessInput(input){// then a miracle occursreturn{ left, right, top, bottom };}// 调用时只选择需要的数据const{ left, right }=processInput(input);
// badconsterrorMessage='This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.';// badconsterrorMessage='This is a super long error that was thrown because \of Batman. When you stop to think about how Batman had anything to do \with this, you would get nowhere \fast.';// goodconsterrorMessage='This is a super long error that was thrown because '+'of Batman. When you stop to think about how Batman had anything to do '+'with this, you would get nowhere fast.';
// badfunctionsayHi(name){return'How are you, '+name+'?';}// badfunctionsayHi(name){return['How are you, ',name,'?'].join();}// goodfunctionsayHi(name){return`How are you, ${name}?`;}
constnumbers=[1,2,3,4,5];// badletsum=0;for(letnumofnumbers){sum+=num;}sum===15;// goodletsum=0;numbers.forEach((num)=>sum+=num);sum===15;// best (use the functional force)constsum=numbers.reduce((total,num)=>total+num,0);sum===15;
// badconstitems=getItems(),goSportsTeam=true,dragonball='z';// bad// (compare to above, and try to spot the mistake)constitems=getItems(),goSportsTeam=true;dragonball='z';// goodconstitems=getItems();constgoSportsTeam=true;constdragonball='z';
// goodfunction(){test();console.log('doing stuff..');//..other stuff..constname=getName();if(name==='test'){returnfalse;}returnname;}// bad - unnecessary function callfunction(hasName){constname=getName();if(!hasName){returnfalse;}this.setFirstName(name);returntrue;}// goodfunction(hasName){if(!hasName){returnfalse;}constname=getName();this.setFirstName(name);returntrue;}
functionexample(){console.log(anonymous);// => undefinedanonymous();// => TypeError anonymous is not a functionvaranonymous=function(){console.log('anonymous function expression');};}
functionexample(){console.log(named);// => undefinednamed();// => TypeError named is not a functionsuperPower();// => ReferenceError superPower is not definedvarnamed=functionsuperPower(){console.log('Flying');};}// the same is true when the function name// is the same as the variable name.functionexample(){console.log(named);// => undefinednamed();// => TypeError named is not a functionvarnamed=functionnamed(){console.log('named');}}
// bad// make() returns a new element// based on the passed in tag name//// @param {String} tag// @return {Element} elementfunctionmake(tag){// ...stuff...returnelement;}// good/** * make() returns a new element * based on the passed in tag name * * @param {String} tag * @return {Element} element */functionmake(tag){// ...stuff...returnelement;}
// badconstactive=true;// is current tab// good// is current tabconstactive=true;// badfunctiongetType(){console.log('fetching type...');// set the default type to 'no type'consttype=this._type||'no type';returntype;}// goodfunctiongetType(){console.log('fetching type...');// set the default type to 'no type'consttype=this._type||'no type';returntype;}
17.3 给注释增加 FIXME 或 TODO 的前缀可以帮助其他开发者快速了解这是一个需要复查的问题,或是给需要实现的功能提供一个解决方式。这将有别于常见的注释,因为它们是可操作的。使用 FIXME -- need to figure this out 或者 TODO -- need to implement。
// file contentsclassCheckBox{// ...}exportdefaultCheckBox;// in some other file// badimportCheckBoxfrom'./checkBox';// badimportCheckBoxfrom'./check_box';// goodimportCheckBoxfrom'./CheckBox';
24.1 当给事件附加数据时(无论是 DOM 事件还是私有事件),传入一个哈希而不是原始值。这样可以让后面的贡献者增加更多数据到事件数据而无需找出并更新事件的每一个处理器。例如,不好的写法:
// bad$(this).trigger('listingUpdated',listing.id);
...
$(this).on('listingUpdated',function(e,listingId){// do something with listingId});
更好的写法:
// good$(this).trigger('listingUpdated',{listingId : listing.id});
...
$(this).on('listingUpdated',function(e,data){// do something with data.listingId});
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Airbnb JavaScript Style Guide() {
用更合理的方式写 JavaScript
ES5 的编码规范请查看版本一,版本二。
翻译自 Airbnb JavaScript Style Guide 。
目录
类型
1.1 基本类型: 直接存取基本类型。
字符串
数值
布尔类型
null
undefined
1.2 复杂类型: 通过引用的方式存取复杂类型。
对象
数组
函数
⬆ 返回目录
引用
2.1 对所有的引用使用
const
;不要使用var
。2.2 如果你一定需要可变动的引用,使用
let
代替var
。2.3 注意
let
和const
都是块级作用域。⬆ 返回目录
对象
3.1 使用字面值创建对象。
3.2 如果你的代码在浏览器环境下执行,别使用 保留字 作为键值。这样的话在 IE8 不会运行。 更多信息。 但在 ES6 模块和服务器端中使用没有问题。
3.3 使用同义词替换需要使用的保留字。
3.4 创建有动态属性名的对象时,使用可被计算的属性名称。
3.5 使用对象方法的简写。
3.6 使用对象属性值的简写。
3.7 在对象属性声明前把简写的属性分组。
⬆ 返回目录
数组
4.1 使用字面值创建数组。
4.2 向数组添加元素时使用 Arrary#push 替代直接赋值。
4.3 使用拓展运算符
...
复制数组。4.4 使用 Array#from 把一个类数组对象转换成数组。
⬆ 返回目录
解构
5.1 使用解构存取和使用多属性对象。
5.2 对数组使用解构赋值。
5.3 需要回传多个值时,使用对象解构,而不是数组解构。
⬆ 返回目录
Strings
6.1 字符串使用单引号
''
。6.2 字符串超过 80 个字节应该使用字符串连接号换行。
6.3 注:过度使用字串连接符号可能会对性能造成影响。jsPerf 和 讨论.
6.4 程序化生成字符串时,使用模板字符串代替字符串连接。
⬆ 返回目录
函数
7.1 使用函数声明代替函数表达式。
7.2 函数表达式:
7.3 永远不要在一个非函数代码块(
if
、while
等)中声明一个函数,把那个函数赋给一个变量。浏览器允许你这么做,但它们的解析表现不一致。7.4 注意: ECMA-262 把
block
定义为一组语句。函数声明不是语句。阅读 ECMA-262 关于这个问题的说明。7.5 永远不要把参数命名为
arguments
。这将取代原来函数作用域内的arguments
对象。7.6 不要使用
arguments
。可以选择 rest 语法...
替代。7.7 直接给函数的参数指定默认值,不要使用一个变化的函数参数。
7.8 直接给函数参数赋值时需要避免副作用。
⬆ 返回目录
箭头函数
8.1 当你必须使用函数表达式(或传递一个匿名函数)时,使用箭头函数符号。
8.2 如果一个函数适合用一行写出并且只有一个参数,那就把花括号、圆括号和
return
都省略掉。如果不是,那就不要省略。⬆ 返回目录
构造器
9.1 总是使用
class
。避免直接操作prototype
。9.2 使用
extends
继承。9.3 方法可以返回
this
来帮助链式调用。9.4 可以写一个自定义的
toString()
方法,但要确保它能正常运行并且不会引起副作用。⬆ 返回目录
模块
10.1 总是使用模组 (
import
/export
) 而不是其他非标准模块系统。你可以编译为你喜欢的模块系统。10.2 不要使用通配符 import。
10.3 不要从 import 中直接 export。
⬆ 返回目录
Iterators and Generators
11.1 不要使用 iterators。使用高阶函数例如
map()
和reduce()
替代for-of
。11.2 现在还不要使用 generators。
⬆ 返回目录
属性
12.1 使用
.
来访问对象的属性。12.2 当通过变量访问属性时使用中括号
[]
。⬆ 返回目录
变量
13.1 一直使用
const
来声明变量,如果不这样做就会产生全局变量。我们需要避免全局命名空间的污染。地球队长已经警告过我们了。(译注:全局,global 亦有全球的意思。地球队长的责任是保卫地球环境,所以他警告我们不要造成「全球」污染。)13.2 使用
const
声明每一个变量。13.3 将所有的
const
和let
分组13.4 在你需要的地方给变量赋值,但请把它们放在一个合理的位置。
⬆ 返回目录
Hoisting
14.1
var
声明会被提升至该作用域的顶部,但它们赋值不会提升。let
和const
被赋予了一种称为「暂时性死区(Temporal Dead Zones, TDZ)」的概念。这对于了解为什么 type of 不再安全相当重要。14.2 匿名函数表达式的变量名会被提升,但函数内容并不会。
14.3 命名的函数表达式的变量名会被提升,但函数名和函数函数内容并不会。
14.4 函数声明的名称和函数体都会被提升。
想了解更多信息,参考 Ben Cherry 的 JavaScript Scoping & Hoisting。
⬆ 返回目录
比较运算符和等号
15.1 优先使用
===
和!==
而不是==
和!=
.15.2 条件表达式例如
if
语句通过抽象方法ToBoolean
强制计算它们的表达式并且总是遵守下面的规则:''
被计算为 false,否则为 true15.3 使用简写。
15.4 想了解更多信息,参考 Angus Croll 的 Truth Equality and JavaScript。
⬆ 返回目录
代码块
16.1 使用大括号包裹所有的多行代码块。
16.2 如果通过
if
和else
使用多行代码块,把else
放在if
代码块关闭括号的同一行。⬆ 返回目录
注释
17.1 使用
/** ... */
作为多行注释。包含描述、指定所有参数和返回值的类型和值。17.2 使用
//
作为单行注释。在评论对象上面另起一行使用单行注释。在注释前插入空行。17.3 给注释增加
FIXME
或TODO
的前缀可以帮助其他开发者快速了解这是一个需要复查的问题,或是给需要实现的功能提供一个解决方式。这将有别于常见的注释,因为它们是可操作的。使用FIXME -- need to figure this out
或者TODO -- need to implement
。17.4 使用
// FIXME
: 标注问题。17.5 使用
// TODO
: 标注问题的解决方式。⬆ 返回目录
空白
18.1 使用 2 个空格作为缩进。
18.2 在花括号前放一个空格。
18.3 在控制语句(
if
、while
等)的小括号前放一个空格。在函数调用及声明中,不在函数的参数列表前加空格。18.4 使用空格把运算符隔开。
18.5 在文件末尾插入一个空行。
18.5 在使用长方法链时进行缩进。使用前面的点
.
强调这是方法调用而不是新语句。18.6 在块末和新语句前插入空行。
⬆ 返回目录
逗号
19.1 行首逗号:不需要。
19.2 增加结尾的逗号: 需要。
⬆ 返回目录
分号
20.1 使用分号
Read more.
⬆ 返回目录
类型转换
21.1 在语句开始时执行类型转换。
21.2 字符串:
21.3 对数字使用
parseInt
转换,并带上类型转换的基数。21.4 如果因为某些原因 parseInt 成为你所做的事的瓶颈而需要使用位操作解决性能问题时,留个注释说清楚原因和你的目的。
21.5 注: 小心使用位操作运算符。数字会被当成 64 位值,但是位操作运算符总是返回 32 位的整数(参考)。位操作处理大于 32 位的整数值时还会导致意料之外的行为。关于这个问题的讨论。最大的 32 位整数是 2,147,483,647:
21.6 布尔:
⬆ 返回目录
命名规则
22.1 避免单字母命名。命名应具备描述性。
22.2 使用驼峰式命名对象、函数和实例。
22.3 使用帕斯卡式命名构造函数或类。
22.4 不要使用下划线
_
结尾或开头来命名属性和方法。22.5 别保存
this
的引用。使用箭头函数或 Function#bind。22.6 如果你的文件只输出一个类,那你的文件名必须和类名完全保持一致。
22.7 当你导出默认的函数时使用驼峰式命名。你的文件名必须和函数名完全保持一致。
22.8 当你导出单例、函数库、空对象时使用帕斯卡式命名。
⬆ 返回目录
存取器
23.1 属性的存取函数不是必须的。
23.2 如果你需要存取函数时使用
getVal()
和setVal('hello')
。23.3 如果属性是布尔值,使用
isVal()
或hasVal()
。23.4 创建
get()
和set()
函数是可以的,但要保持一致。⬆ 返回目录
事件
24.1 当给事件附加数据时(无论是 DOM 事件还是私有事件),传入一个哈希而不是原始值。这样可以让后面的贡献者增加更多数据到事件数据而无需找出并更新事件的每一个处理器。例如,不好的写法:
更好的写法:
⬆ 返回目录
jQuery
25.1 使用
$
作为存储 jQuery 对象的变量名前缀。25.2 缓存 jQuery 查询。
25.3 对 DOM 查询使用层叠
$('.sidebar ul')
或 父元素 > 子元素$('.sidebar > ul')
。 jsPerf25.4 对有作用域的 jQuery 对象查询使用
find
。⬆ 返回目录
ECMAScript 5 兼容性
⬆ 返回目录
ECMAScript 6 规范
⬆ 返回目录
测试
28.1 Yup.
⬆ 返回目录
性能
map()
,reduce()
, andfilter()
optimized for traversing arrays?⬆ 返回目录
相关资源(英文)
了解 ES6
看看这个
工具
其他风格指南
其他风格
拓展阅读
书籍
博客
播客
⬆ 返回目录
使用情况
下列组织应用这份风格指南。
⬆ 返回目录
翻译
这份风格指南也有其他语言的译本:
JavaScript 编码规范说明
讨论 JavaScript
贡献者
许可协议
(The MIT License)
Copyright (c) 2014 Airbnb
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
⬆ 返回目录
修订
我们鼓励您派生本指南和更改规则以适应您的团队需求。您可以在下方列出对本风格指南的修改,以便定期更新本指南而无需处理合并冲突。
};
The text was updated successfully, but these errors were encountered: