插件
vscode必须安装插件Prettier - Code formatter, 格式化代码快捷键 Shift + Alt + F
Prettier is an opinionated code formatter. It enforces a consistent style by parsing your code and re-printing it with its own rules that take the maximum line length into account, wrapping code when necessary.
importClass和require谁先谁后
runtime.loadDex("./yashu.dex");
importClass(android.graphics.Rect);
let yashu = require("./yashu");
界面
界面优先显示, 其他操作靠后, 缓解用户焦虑
命名约定
- 避免单个字符名,让你的变量名有描述意义。
// bad
function q() {
// ...stuff...
}
// good
function query() {
// ..stuff..
}
- 当命名对象、函数和实例时使用驼峰命名规则
// bad
var OBJEcttsssss = {};
var this_is_my_object = {};
var this-is-my-object = {};
function c() {};
var u = new user({
name: 'Bob Parr'
});
// good
var thisIsMyObject = {};
function thisIsMyFunction() {};
var user = new User({
name: 'Bob Parr'
});
- 当命名构造函数或类时使用驼峰式大写
// bad
function user(options) {
this.name = options.name;
}
var bad = new user({
name: 'nope'
});
// good
function User(options) {
this.name = options.name;
}
var good = new User({
name: 'yup'
});
- 命名私有属性时前面加个下划线
_
// bad
this.__firstName__ = 'Panda';
this.firstName_ = 'Panda';
// good
this._firstName = 'Panda';
- 当保存对
this
的引用时使用_this
.
// bad
function() {
var self = this;
return function() {
console.log(self);
};
}
// bad
function() {
var that = this;
return function() {
console.log(that);
};
}
// good
function() {
var _this = this;
return function() {
console.log(_this);
};
}
文件命名规范
- 谷歌
File names must be all lowercase and may include underscores (
_
) or dashes (-
), but no additional punctuation. Follow the convention that your project uses. Filenames’ extension must be.js
.
- github
- 其他1
Js 文件命名规范
- 字母全部小写
- 不要带空格
- 用破折号(-)连接单词
- 库文件可用逗点(.),用于体现版本或从属关系
Demo
- vue.min.js
- vue-router.js
- jquery.form.js
- jquery-1.4.2.min.js
- 其他2
1、项目命名
全部采用小写方式,以下划线分割战场
例如:come_money
2、目录命名
参照项目命名,如有复数结构时,采用复数命名法
例如: moneys,assets,components。。。。
3、js、css、less、sass、 stylus文件命名
全部采用小驼峰命名规则
例如: comeMoney.js、moneyCome.css、moneyCome.stylus
4、VUE组件Components命名
所有组件名字大驼峰格式
例如: ComeMoney.vue、MoneyCome.vue
- 上面的惯例仅供参考,最终还是尊重个人习惯。不过如果你在项目中引用了某个框架或库,就最好优先使用他们的命名习惯。另外,一个项目中最好统一使用一种命名规则,这样方便自己和其他开发人员识别。
对象
- 请使用对象方法的简写方式, 属性不可简写, 方法可以简写
// bad
const item = {
value: 1,
addValue: function (val) {
return item.value + val
}
}
// good
const item = {
value: 1,
addValue (val) {
return item.value + val
}
}
- 不要直接使用
Object.prototype
的方法, 例如hasOwnProperty
,propertyIsEnumerable
和isPrototypeOf
方法
原因:这些方法可能会被对象自身的同名属性覆盖 - 比如
{ hasOwnProperty: false }
或者对象可能是一个null
对象(Object.create(null)
)
// bad
console.log(object.hasOwnProperty(key))
// good
console.log(Object.prototype.hasOwnProperty.call(object, key))
// best
const has = Object.prototype.hasOwnProperty // cache the lookup once, in module scope.
console.log(has.call(object, key))
数组
- 当你需要拷贝数组时使用slice
var len = items.length,
itemsCopy = [],
i;
// bad
for (i = 0; i < len; i++) {
itemsCopy[i] = items[i];
}
// good
itemsCopy = items.slice();
- 使用slice将类数组的对象转成数组
function trigger() {
var args = Array.prototype.slice.call(arguments);
...
}
解构赋值
- 当需要使用数组的多个值时,请使用解构赋值
const arr = [1, 2, 3, 4]
// bad
const first = arr[0]
const second = arr[1]
// good
const [first, second] = arr
字符串
- 字符串太长的时候,请不要使用字符串连接符换行
\
,而是使用+
const str = '牙叔教程 牙叔教程 牙叔教程' +
'牙叔教程 牙叔教程 牙叔教程' +
'牙叔教程 牙叔教程'
- 不要在字符串中使用不必要的转义字符
// bad
const foo = '\'this\' \i\s \"quoted\"'
// good
const foo = '\'this\' is "quoted"'
- 编程时使用join而不是字符串连接来构建字符串
var items,
messages,
length, i;
messages = [{
state: 'success',
message: 'This one worked.'
},{
state: 'success',
message: 'This one worked as well.'
},{
state: 'error',
message: 'This one did not work.'
}];
length = messages.length;
// bad
function inbox(messages) {
items = '<ul>';
for (i = 0; i < length; i++) {
items += '<li>' + messages[i].message + '</li>';
}
return items + '</ul>';
}
// good
function inbox(messages) {
items = [];
for (i = 0; i < length; i++) {
items[i] = messages[i].message;
}
return '<ul><li>' + items.join('</li><li>') + '</li></ul>';
}
函数
- 函数表达式
// 匿名函数表达式
var anonymous = function() {
return true;
};
// 有名函数表达式
var named = function named() {
return true;
};
// 立即调用函数表达式
(function() {
console.log('Welcome to the Internet. Please follow me.');
})();
- 用圆括号包裹自执行匿名函数
(function () {
console.log('Welcome to the Internet. Please follow me.')
}())
- 不要在一个非函数块里声明一个函数,把那个函数赋给一个变量。
// bad
if (currentUser) {
function test() {
console.log('Nope.');
}
}
// good
if (currentUser) {
var test = function test() {
console.log('Yup.');
};
}
- 绝对不要把参数命名为
arguments
, 这将会逾越函数作用域内传过来的arguments
对象.
// bad
function nope(name, options, arguments) {
// ...stuff...
}
// good
function yup(name, options, args) {
// ...stuff...
}
箭头函数
- 当你必须使用函数表达式(传递匿名函数)时,使用箭头函数标记
// 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
})
对象属性
- 使用
.
来访问对象属性
const joke = {
name: 'haha',
age: 28
}
// bad
const name = joke['name']
// good
const name = joke.name
- 当访问的属性是变量时使用
[]
const luke = {
jedi: true,
age: 28,
}
function getProp (prop) {
return luke[prop]
}
const isJedi = getProp('jedi')
变量声明
- 在作用域顶部声明变量,避免变量声明和赋值引起的相关问题。
// bad
function() {
test();
console.log('doing stuff..');
//..other stuff..
var name = getName();
if (name === 'test') {
return false;
}
return name;
}
// good
function() {
var name = getName();
test();
console.log('doing stuff..');
//..other stuff..
if (name === 'test') {
return false;
}
return name;
}
// bad
function() {
var name = getName();
if (!arguments.length) {
return false;
}
return true;
}
// good
function() {
if (!arguments.length) {
return false;
}
var name = getName();
return true;
}
- 将所有的
const
和let
分组
// bad
let a
const b
let c
const d
let e
// good
const b
const d
let a
let c
let e
- 变量不要进行链式赋值
原因:变量链式赋值会创建隐藏的全局变量
// bad
(function example() {
// JavaScript interprets this as
// let a = ( b = ( c = 1 ) );
// The let keyword only applies to variable a; variables b and c become
// global variables.
let a = b = c = 1
}())
console.log(a) // throws ReferenceError
console.log(b) // 1
console.log(c) // 1
// good
(function example() {
let a = 1
let b = a
let c = a
}())
console.log(a) // throws ReferenceError
console.log(b) // throws ReferenceError
console.log(c) // throws ReferenceError
// the same applies for `const`
- 不允许出现未被使用的变量
原因:声明但未被使用的变量通常是不完全重构犯下的错误.这种变量在代码里浪费空间并会给读者造成困扰
// bad
var some_unused_var = 42
// Write-only variables are not considered as used.
var y = 10
y = 5
// A read for a modification of itself is not considered as used.
var z = 0
z = z + 1
// Unused function arguments.
function getX (x, y) {
return x
}
// good
function getXPlusY (x, y) {
return x + y
}
const x = 1
const y = a + 2
alert(getXPlusY(x, y))
// 'type' is ignored even if unused because it has a rest property sibling.
// This is a form of extracting an object that omits the specified keys.
const { type, ...coords } = data
// 'coords' is now the 'data' object without its 'type' property.
Hoisting
-
var
存在变量提升的情况,即var
声明会被提升至该作用域的顶部,但是他们的赋值并不会。而const
和let
并不存在这种情况,他们被赋予了 Temporal Dead Zones, TDZ, 了解 typeof 不再安全很重要
function example () {
console.log(notDefined) // => throws a ReferenceError
}
function example () {
console.log(declareButNotAssigned) // => undefined
var declaredButNotAssigned = true
}
function example () {
let declaredButNotAssigned
console.log(declaredButNotAssigned) // => undefined
declaredButNotAssigned = true
}
function example () {
console.log(declaredButNotAssigned) // => throws a ReferenceError
console.log(typeof declaredButNotAssigned) // => throws a ReferenceError
const declaredButNotAssigned = true
}
- 匿名函数的变量名会提升,但函数内容不会
function example () {
console.log(anonymous) // => undefined
anonymous()
var anonymous = function () {
console.log('test')
}
}
- 命名的函数表达式的变量名会被提升,但函数名和函数函数内容并不会
function example() {
console.log(named) // => undefined
named() // => TypeError named is not a function
superPower() // => ReferenceError superPower is not defined
var named = function superPower () {
console.log('Flying')
}
}
function example() {
console.log(named) // => undefined
named() // => TypeError named is not a function
var named = function named () {
console.log('named')
}
}
比较运算符&相等
- 使用
===
和!==
而非==
和!=
,eslint: eqeqeq - 条件声明例如
if
会用ToBoolean
这个抽象方法将表达式转成布尔值并遵循如下规则
-
Objects
等于true
-
Undefined
等于false
-
Null
等于false
-
Booleans
等于布尔值
-
Numbers
在+0
,-0
, 或者NaN
的情况下等于false
, 其他情况是true
-
Strings
为''
时等于false
, 否则是true
if ([0] && []) {
// true
// 数组(即使是空数组)也是对象,对象等于true
}
- 使用快捷方式.
// bad
if (name !== '') {
// ...stuff...
}
// good
if (name) {
// ...stuff...
}
// bad
if (collection.length > 0) {
// ...stuff...
}
// good
if (collection.length) {
// ...stuff...
}
分号
- 自执行函数前后必须加分号
const test = '牙叔教程'
;(() => {
const str = '简单易学'
})();
块
- 给所有多行的块使用大括号
// bad
if (test)
return false;
// good
if (test) return false;
// good
if (test) {
return false;
}
// bad
function() { return false; }
// good
function() {
return false;
}
注释
- 使用
/** ... */
进行多行注释,包括描述,指定类型以及参数值和返回值
// bad
// make() returns a new element
// based on the passed in tag name
//
// @param <String> tag
// @return <Element> element
function make(tag) {
// ...stuff...
return element;
}
// good
/**
* make() returns a new element
* based on the passed in tag name
*
* @param <String> tag
* @return <Element> element
*/
function make(tag) {
// ...stuff...
return element;
}
- 使用
//
进行单行注释,在评论对象的上面进行单行注释,注释前放一个空行.
// bad
var active = true; // is current tab
// good
// is current tab
var active = true;
// bad
function getType() {
console.log('fetching type...');
// set the default type to 'no type'
var type = this._type || 'no type';
return type;
}
// good
function getType() {
console.log('fetching type...');
// set the default type to 'no type'
var type = this._type || 'no type';
return type;
}
- 如果你有一个问题需要重新来看一下或如果你建议一个需要被实现的解决方法的话需要在你的注释前面加上
FIXME
或TODO
帮助其他人迅速理解
function Calculator() {
// FIXME: shouldn't use a global here
total = 0;
return this;
}
function Calculator() {
// TODO: total should be configurable by an options param
this.total = 0;
return this;
}
存取器
- 属性的存取器函数不是必需的
- 如果你确实有存取器函数的话使用getVal() 和 setVal(‘hello’)
// bad
dragon.age();
// good
dragon.getAge();
// bad
dragon.age(25);
// good
dragon.setAge(25);
- 如果属性是布尔值,使用isVal() 或 hasVal()
// bad
if (!dragon.age()) {
return false;
}
// good
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(key, val) {
this[key] = val;
};
Jedi.prototype.get = function(key) {
return this[key];
};
构造器
- 给对象原型分配方法,而不是用一个新的对象覆盖原型,覆盖原型会使继承出现问题。
function Jedi() {
console.log('new jedi');
}
// bad
Jedi.prototype = {
fight: function fight() {
console.log('fighting');
},
block: function block() {
console.log('blocking');
}
};
// good
Jedi.prototype.fight = function fight() {
console.log('fighting');
};
Jedi.prototype.block = function block() {
console.log('blocking');
};
- 方法可以返回
this
帮助方法可链。
// bad
Jedi.prototype.jump = function() {
this.jumping = true;
return true;
};
Jedi.prototype.setHeight = function(height) {
this.height = height;
};
var luke = new Jedi();
luke.jump(); // => true
luke.setHeight(20) // => undefined
// good
Jedi.prototype.jump = function() {
this.jumping = true;
return this;
};
Jedi.prototype.setHeight = function(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();
};