Airbnb JavaScript 编码风格指南(2018年最新版)
vue-cli脚手架build目录中的webpack.base.conf.js配置文件
ESlint是一个语法规则和代码风格检查工具,可以用来保证代码风格统一,方便以后维护。
使用vue-cli创建基本项目,默认安装ESlint。
在build/webpack.base.conf.js
下:
// 引入config目录下的index.js配置文件,主要用来定义一些开发和生产环境的属性,其中包含是否使用 eslint 的判断语句 const config = require('../config') // ... // 创建 eslint 规则 const createLintingRule = () => ({ test: /\.(js|vue)$/, loader: 'eslint-loader', enforce: 'pre', include: [resolve('src'), resolve('test')], options: { formatter: require('eslint-friendly-formatter'), emitWarning: !config.dev.showEslintErrorsInOverlay } }) // module用来解析不同的模块 module: { rules: [ // 使用 eslint 判断 ...(config.dev.useEslint ? [createLintingRule()] : []), ] }
module.exports = { dev: { // ... // Use Eslint Loader 是否使用ESlint? // If true, your code will be linted during bundling and // linting errors and warnings will be shown in the console. // 代码在执行过程中,将会在console中显示错误 和 警告 useEslint: true, // If true, eslint errors and warnings will also be shown in the error overlay。 eslint显示错误和警告的错误也将被覆盖 // in the browser. showEslintErrorsInOverlay: false, } // .... }
vue-cli中的ESlint配置文件eslintrc.js详解
类型
-
基本类型
-
对于基本类型的操作时对值的操作
-
-
复杂类型
-
对于复杂类型的操作是对引用的操作
-
对象
-
尽量使用字面量创建对象
-
不要使用保留字作为属性键值
-
使用可读性强的同义词来代替保留字
数组
-
尽量使用字面量创建数组
-
使用
arr.push()
方法来添加元素 -
复制数组使用
arr.slice
字符串
-
使用单引号
''
定义字符串 -
超过100个字符串应该写成多行形式并使用字符串连接符
+
连接(过度使用字符串连接符可能会影响性能 ) -
在代码中构建字符串时,使用
arr.join()
方法,而不是使用字符串连接符+
函数
-
永远不要再非函数代码块(if,while)中声明函数,但是可以将函数复制给一个变量
-
永远不要将一个参数命名为
arguments
,这么做会覆盖每个函数默认的arguments
对象
属性
-
使用点号
.
来获取对象的属性 -
当需要获取的属性键值是一个变量来给出,可以使用
[]
来获取
变量
-
声明变量的使用永远要写上
var
,不这么做的话将会得到一个全局变量,并因此污染全局变量的命名空间。(现在一般用const
和let
) -
每一个变量声明使用一个单独的
var
-
将未赋值变量的声明放在最后,这有利于后面再给变量赋值的使用需要依赖另一个已赋值变量的情况
-
将变量声明放在其作用域的最顶端,这样可以避免变量提升所带来的问题
变量提升
-
变量的声明语句会被解释器自动提升到其作用域的最顶部,但其赋值的语句不会被提升。
-
匿名函数表达式的变量声明会被提升,但函数体不会被提升。
-
有命名的函数表达式的变量声明会被提升,但函数名和函数体都不会被提升。
-
函数声明时解释器会将函数名和函数体都提升到作用域顶部。
比较运算符
-
使用
===
和!==
比使用==
和!=
更理想 -
条件语句在判断表达式值的使用,会使用
ToBoolean
抽象方法将结果强制转化为布尔值-
Objects转化为true
-
Undefined转化为false
-
Null转化为false
-
Booleans不变
-
Numbers如果是+0, -0或NaN转化为false, 否则转化为true
-
Strings如果是空字符串
''
转化为false, 否则转化为true
-
-
使用简短形式
空白符
-
缩进2个空格
-
左大括号之前留一个空格
-
控制语句
if,while
的做小括号留一个空格,函数的阐述列表前不要留空格 -
将运算符用空格隔开
-
文件最后以一个单独的换行符结尾。
-
遇到很长的方法调用链,使用换行缩进的方式(参照下面的代码),并以点号
.
开头,强调此行是一个方法而非一个新的语句。
// 不推荐 $('#items').find('.selected').highlight().end().find('.open').updateCount();
- 在代码块结束和新语句之间留一个空行。
-
放在行首的逗号: 不要使用
-
对象或数组末尾额外的逗号: 不要使用
分号
-
请使用
类型转化和强制转化
-
在语句开始的时候执行类型的强制转化
-
字符串
// 推荐 var totalScore = '' + this.reviewScore; // 推荐 var totalScore = this.reviewScore + ' total score';
- 数字类型转化时使用
parseInt
,并且总是带上基数
// 推荐 var val = Number(inputValue); // 推荐 var val = parseInt(inputValue, 10);
// 推荐 /** * parseInt是我代码缓慢的元凶, * 使用移位操作来将字符串转换成数字可解此忧 */ var val = inputValue >> 0;
var age = 0; // 不推荐 var hasAge = new Boolean(age); // 推荐 var hasAge = Boolean(age); // 推荐 var hasAge = !!age;
-
避免单字母的命名,尽量使用有意义的命名方式。
-
对象、函数、实例命名时,使用骆驼命名(小驼峰命名,例如:
thisIsMyObject
) -
构造方法或类的命名使用帕斯卡命名(大驼峰命名)。
-
命名私有属性的时候,以下划线
_
开头 -
要保存一个到
this
的引用,请使用_this
来命名变量。 -
给你的函数命名,这将有利于调试时代码栈的追踪。
// 不推荐 var log = function (msg) { console.log(msg); }; // 推荐 var log = function log(msg) { console.log(msg); };
- 如果你的源码文件中只导出(exports)了一个类,请保持你的文件名与类名一致
// 文件内容 class CheckBox { // ... } module.exports = CheckBox; // 在其他文件中 // 不推荐 var CheckBox = require('./checkBox'); // 不推荐 var CheckBox = require('./check_box'); // 推荐 var CheckBox = require('./CheckBox');
-
属性存取器方法不是必需的。
-
如果你要定义属性存取器,按照getVal()和setVal('hello')的模式来命名。
// 不推荐 dragon.age(); // 推荐 dragon.getAge(); // 不推荐 dragon.age(25); // 推荐 dragon.setAge(25);
- 如果属性是布尔型,使用isVal()或hasVal()的形式
// 不推荐 if (!dragon.age()) { return false; } // 推荐 if (!dragon.hasAge()) { return false; }
- 创建get()和set()函数也是可以的,但要保持其行为的一致性。
function Jedi(options) { options || (options = {}); var lightsaber = options.lightsaber || 'blue'; this.set('lightsaber', lightsaber); } Jedi.prototype.set = function set(key, val) { this[key] = val; }; Jedi.prototype.get = function get(key) { return this[key]; };
-
将新增方法赋值给对象的原型(prototype),而不要直接用新的对象覆盖对象的原型。 如果每次都覆盖对象的原型,就不能实现继承了,因为每次你都会直接覆盖掉基类的所有方法。
// 不推荐 Jedi.prototype = { fight: function fight() { console.log('fighting'); }, block: function block() { console.log('blocking'); } }; // 推荐 Jedi.prototype.fight = function fight() { console.log('fighting'); }; Jedi.prototype.block = function block() { console.log('blocking'); };
// 不推荐 Jedi.prototype.jump = function jump() { this.jumping = true; return true; }; Jedi.prototype.setHeight = function setHeight(height) { this.height = height; }; var luke = new Jedi(); luke.jump(); // => true luke.setHeight(20); // => undefined // 推荐 Jedi.prototype.jump = function jump() { this.jumping = true; return this; }; Jedi.prototype.setHeight = function setHeight(height) { this.height = height; return this; }; var luke = new Jedi(); luke.jump() .setHeight(20);
- 创建一个自定义的toString()也是可以的,但要确保其正确性,并注意它对代码的其他地方会不会产生影响。
function Jedi(options) { options || (options = {}); this.name = options.name || 'no name'; } Jedi.prototype.getName = function getName() { return this.name; }; Jedi.prototype.toString = function toString() { return 'Jedi - ' + this.getName(); };
-
当你需要将数据绑定到一个事件(无论是DOM事件还是其他的事件)的时候,不要直接传入数据对象本身,将其包装到一个键值对象中再传入,因为你不能确保后续操作中不需要传入其他更多的数据到本事件中。例如, 下面这样就是不好的:
// 不推荐 $(this).trigger('listingUpdated', listing.id); ... $(this).on('listingUpdated', function (e, listingId) { // do something with listingId });
更好的做法是:
// 推荐 $(this).trigger('listingUpdated', { listingId : listing.id }); ... $(this).on('listingUpdated', function (e, data) { // do something with data.listingId });
-
模块应该以一个
!
开头,确保如果本模块被合并到另一个第三方模块的末尾,而这个第三方模块忘记了结尾的分号的时候,不会报错。更多解释 -
文件应该按骆驼命名(小驼峰命名)规则命名。如果文件夹中只有一个文件,文件夹名和文件名保持一致。
-
添加一个名叫
noConflict()
的方法将到处模块设置为前一个版本并返回这个模块。 -
在模块顶部总是要声明
'use strict';
。
// fancyInput/fancyInput.js !function (global) { 'use strict'; var previousFancyInput = global.FancyInput; function FancyInput(options) { this.options = options || {}; } FancyInput.noConflict = function noConflict() { global.FancyInput = previousFancyInput; return FancyInput; }; global.FancyInput = FancyInput; }(this);
-
jQuery对象的变量命名以
$
开头。
// 不推荐 var sidebar = $('.sidebar'); // 推荐 var $sidebar = $('.sidebar');
- 缓存jQuery选择器结果。
// 不推荐 function setSidebar() { $('.sidebar').hide(); // ...stuff... $('.sidebar').css({ 'background-color': 'pink' }); } // 推荐 function setSidebar() { var $sidebar = $('.sidebar'); $sidebar.hide(); // ...stuff... $sidebar.css({ 'background-color': 'pink' }); }
-
-
使用
find
来查找某个范围内的jQuery对象。
// 不推荐 $('ul', '.sidebar').hide(); // 不推荐 $('.sidebar').find('ul').hide(); // 推荐 $('.sidebar ul').hide(); // 推荐 $('.sidebar > ul').hide(); // 推荐 $sidebar.find('ul').hide();