一、对象
1.对象创建时,属性键名不要使用保留字
// bad
var person = {
default: { name: 'jl' },
private: true
};
// good
var superman = {
defaults: { name: 'jl' },
hidden: true
};
二、数组
1.向数组增加元素时使用push,避免使用数组位直接赋值
var someStack = [];
// bad
someStack[someStack.length] = 'abracadabra';
// good
someStack.push('abracadabra');
2.需要拷贝数组时,使用slice方法或ES6的[...array]展开方法,此外直接赋值会导致共享数组引用,进而导致数组元素错误修改
var arr=[1,2,3,4,5]
var arrCopy=[]
//bad
for(var i=0;i<arr.length;i++){
arrCopy[i]=arr[i]
}
//good
arrCopy=arr.slice()
3.类数组对象转为数组时,使用Array.slice方法
function transfer() {
var args=Array.prototype.slice.call(arguments)
...
}
三、字符串
1.使用单引号包裹字符串
// bad
var name = "Bob Parr";
// good
var name = 'Bob Parr';
四、属性
1.确定属性名时,使用.访问对象属性
var person = {
name: 'jl',
age: 28
};
// bad
var name = person['name'];
// good
var name = person.name;
2. 不确定属性名时,使用[]访问对象属性
var person = {
name: 'jl',
age: 28
};
function getProp(prop) {
return person[prop];
}
var name = getProp('name');
五、变量
1.用var声明每一个变量,从而避免 ; 与 , 换错
// bad
var items = getItems(),
goSportsTeam = true,
dragonball = 'z';
// bad
// (跟上面的代码比较一下,看看哪里错了)
var items = getItems(),
goSportsTeam = true;
dragonball = 'z';
// good
var items = getItems();
var goSportsTeam = true;
var dragonball = 'z';
2.最后再声明未赋值的变量,当你需要引用前面的变量赋值时将变得十分有用
// bad
var i, len, dragonball,
items = getItems(),
goSportsTeam = true;
// bad
var i;
var items = getItems();
var dragonball;
var goSportsTeam = true;
var len;
// good
var items = getItems();
var goSportsTeam = true;
var dragonball;
var length;
var i;
六、提升
1.变量声明会提升至作用域顶部,但赋值则不会
// 我们知道引用不存在的变量名会导致不能正常工作(假设这里没有名为 notDefined 的全局变量)
function example() {
console.log(notDefined); // => throws a ReferenceError
}
// 但由于变量声明提升的原因,在一个变量引用后再创建它的变量声明将可以正常工作。
// 注:变量赋值为 `true` 的操作不会提升。
function example() {
console.log(declaredButNotAssigned); // => undefined
var declaredButNotAssigned = true;
}
// 解释器会把变量声明提升到作用域顶部,意味着我们的例子将被重写成:
function example() {
var declaredButNotAssigned;
console.log(declaredButNotAssigned); // => undefined
declaredButNotAssigned = true;
}
2.匿名函数表达式会提升变量名,但不会提升函数的赋值
function func() {
console.log(anonymous) // undefined
anonymous() //TypeError anonymous is not a function
var anonymous=function () {
console.log('anonymous function expression');
}
}
3.命名函数表达式会提升变量名,但不会提升函数名或函数体
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('This is a function')
}
}
//当函数名与变量名一致时,仍会出现同样的情况
function example() {
console.log(named) //undefined
named() // TypeError named is not a function
var named=function named(){
console.log('named');
}
}
4.函数式声明提升它们的名字和函数体
function example() {
superPower(); // => Flying
function superPower() {
console.log('Flying');
}
}
七、比较运算符&等号
1.优先使用 === 和 !== 而不是 == 和 !=
2.条件表达式(如if语句)通过抽象方法ToBoolean强制计算其表达式,且总是遵循下面的原则:
- 对象 被计算为 true
- Undefined 被计算为 false
- Null 被计算为 false
- 布尔值 被计算为 布尔的值
- 数字 如果是 +0、-0 或 NaN 被计算为 false,否则为 true
- 字符串 如果是空字符串
''
被计算为 false,否则为 true
// bad
if (name !== '') {
// ...stuff...
}
// good
if (name) {
// ...stuff...
}
// bad
if (collection.length > 0) {
// ...stuff...
}
// good
if (collection.length) {
// ...stuff...
}
3.注释
使用/** ... */作为多行注释,注释中包含描述、指定所有参数和返回值的类型和值。
// 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;
}
八、命名规则
1.避免单字母命名,命名应具备描述性
// bad
function q() {
// ...stuff...
}
// good
function query() {
// ..stuff..
}
2.使用驼峰式命名对象、函数和实例
// bad
var OBJEcttsssss = {};
var this_is_my_object = {};
var o = {};
function c() {}
// good
var thisIsMyObject = {};
function thisIsMyFunction() {}
3.使用帕斯卡式命名构造函数和类
// 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'
});
4.不要使用下划线前/后缀,因为下划线通常表示“私有”属性或变量,而JavaScript中并没有私有的概念,显式定义的属性均为公开属性
// bad
this.__firstName__ = 'Panda';
this.firstName_ = 'Panda';
this._firstName = 'Panda';
// good
this.firstName = 'Panda';
5.不要保存this的引用,应使用Function#bind
// bad
function () {
var self = this;
return function () {
console.log(self);
};
}
// bad
function () {
var that = this;
return function () {
console.log(that);
};
}
// bad
function () {
var _this = this;
return function () {
console.log(_this);
};
}
// good
function () {
return function () {
console.log(this);
}.bind(this);
}
6.如果文件导出一个类,文件名应该和类名完全相同
// file contents
class CheckBox {
// ...
}
module.exports = CheckBox;
// in some other file
// bad
var CheckBox = require('./checkBox');
// bad
var CheckBox = require('./check_box');
// good
var CheckBox = require('./CheckBox');
九、构造函数
1.给对象原型分配方法,而不是使用一个新的对象覆盖原型。覆盖原型将导致继承出现问题:重设原型将覆盖原有原型
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');
};