类型

基本类型


 - string
 - number
 - boolean
 - null
 - undefined
 - symbol(表示独一无二的值,使用时需要注意浏览器是否支持)
     //example
    const symbol1 = Symbol();
    const symbol2 = Symbol(42);
    const symbol3 = Symbol('foo');
    
    console.log(typeof symbol1);
    // expected output: "symbol"
    
    console.log(symbol3.toString());
    // expected output: "Symbol(foo)"
    
    console.log(Symbol('foo') === Symbol('foo'));
    // expected output: false

复杂类型

- array
- object
- function

声明变量

//块级作用域内有效
- let
//块级作用域内有效 不可重复赋值
- const

对象

直接声明

//bad
let obj = new Object();
//good
let obj = {};

动态属性名


//bad
function getKey(key){
    return `${key}`
}
let obj = {
    id:1
    name:"jack"
}  
obj[getKey("age")] = 18;
console.log(obj.age) //18

//good
let obj = {
    name:"jack",
    age:18,
    [getKey("age")]:18
}  

对象方法简写


//bad
let obj = {
    name:"jack",
    age:18,
    show:function(arg){
        console.log(arg)
    }
}  
//good
let obj = {
    name:"jack",
    age:18,
    show(arg){
        console.log(arg)
    }
}  

属性值简写

//bad
let age = 18;
let obj = {
    name:"jack",
    age:age
}
//good
let obj = {   
    age,//简写最好放前面
    name:"jack",
    "data-id":5//键名尽量不加引号,除非没有引号不合法
}

不要直接使用Object.prototype的方法

//不要直接使用Object.prototype的方法,如hasOwnProperty, propertyIsEnumerable和isPrototypeOf
//bad
let obj = {
    id:1,
    name:"jack"
}
obj.hasOwnProperty("name");
//good
Object.prototype.hasOwnProperty.call(obj,"name");
//best
var has = Object.prototype.hasOwnProperty;
has.call(obj,"name")

用变量的解构赋值代替Object.assign()做浅拷贝

//用变量的解构赋值代替Object.assign()做浅拷贝
//bad
let ori = {a:1,b:2};
let copy = Object.assign({},ori,{c:3});
//good
let ori = {a:1,b:2};
let copy = {...ori,c:3};//{a:1,b:2,c:3}
let {a,...notA} = copy; // notA={b:2,c:3}

数组

简洁声明

//bad
let arr = new Array();
//good
let arr = [];

使用push代替直接分配元素给数组

//bad
let arr = [];
arr[arr.length] = "abc";
//good
arr.push("abc");    

扩展运算符...代替数组拷贝

//bad
let arr = [1,2,3];
let copy = [];
for(let i=0;i<len=arr.length,i++){
    copy[i] = arr[i]
}
//good
copy = [...arr]

转换类数组的对象为数组

let div = document.querySelectAll("div");
//good
let arr = Array.from(div);
//best
let arr = [...div]

数组方法中的return

//当function大括号只有一个表达式时,{}和rerun都可以省
//bad
[1,2,3].map(x=>{
    let y = x+1;
    return x*y
}) 
//good
[1,2,3].map(x=>x+1) 

解构赋值

//object
//good
function getFullName(user){
    let {firstName,lastName} = user;
    return `${firstName}${lastName}`
}
//best
function getFullName({firstName,lastName}){
    return `${firstName}${lastName}`
}

//array
let arr = [1,2,3,4];
//bad
let first = arr[0];
let sec = arr[1];
//good
[first,sec] = arr

函数的多个返回值用对象解构赋值

//bad
function processInput(input){
    return [let,top,right,bottom]
}
//good
function processInput(input){
    return {let,top,right,bottom}
}
//use
let {left,bottom} = processInput(input);

字符串

使用单引号

//bad
let str = "hello world";
//good
let str = 'hello world'
             

尽量别转行

//有转行时,当然字符数不超过100的情况尽量别转行
//bad
let str = 'hello world,'+
          'balabalabala';
//good

let str = 'hello world,balabalabala'

字符串变量拼接

//bad
let str = 'hello '+name+' !';
//good
let str =`hello ${name} !`;

函数

复杂名称的函数赋值给一个简洁变量名

  //bad
  let foo= function(){}
  function foo(){}
  //good
  let foo = function getPageFooComponent(){}
  //use
  foo();

别在if while等语句中声明函数

//bad
if(){
    function test(){}
}
//good
let test;
if(){
    test = ()=>{console.log("hello")}
}

别用arguments作为参数名

//bad
function foo(name,arguments){}
//good
function foo(name,arg){}

扩展运算符...代替arguments

//bad
function test(){
    let args = Array.portotype.slice.call(arguments);
    return args.join('');
}
//good
function test(...args){
    return args.join('');
}

默认参数

//bad
funtion test(opt){
    let opt = opt || {}
}
//good
function test(opt={}){

}

别在参数体里面计算

//bad
let a=1;
function test(b = a++){
    
}

将赋值的参数放在最后

//bad
function test(opt = {},name){
}
//good
function test(name,opt = {}){
}

别对参数重新赋值

//bad
function test(a){
    let a=1;
}
function test(a){
   if(!a){
    let a=1;
   }
}
//good
function test(a){
    let b = a || 1;
}
function test(a = 1){
  
}

类&构造方法

用class代替传统的prototype手动方法

//bad
function Queue(contents = []){
    this.queue = [contents];
}
Queue.prototype.pop = function(){
    let value = this.queue[0];
    this.queue.spice(0,1);
    return value;
}
//good
class Queue {
    constructor(contents = []){
        this.queue = [contents]
    }
    pop(){
        let value = this.queue[0];
        this.queue.spice(0,1);
        return value;
    }
}

用extend做继承

//good
class Dog extends Animal{
    yell(){
        return 'wangwang'
    }
}

this的指向

 //bad
 Jedi.prototype.jump = function(){
     this.jumping = true;
     return true;
 }
 Jedi.prototype.setHeight= function(height){
     this.height = height;
 }
 let luck = new Jedi();
 luck.jump();
 luck.setHeight(20);
//good
class Jedi{
    jump(){
        this.jumping = true;
         return true;
    }
    setHeight(height){
        this.height = height;
    }
}
let luck = new Jedi();
luck.jump();
luck.setHeight(20);

子类的构造函数必须执行一次super函数

//bad
class test {
    constructor() {}//空constructor不需要
    
    getName() {
        return this.name;
    }
}
//bad
class test {
    constructor(...args) {
        super(...args)//只是为了继承constructor不需要
    }
}
//good
class test {
    constructor(...args) {
        super(...args)
        this.name = 'key'
    }
}

模块

import/export

//bad
let AirbnbJavascriptGuide = require('./AirbnbJavascriptGuide ');
module.exports = AirbnbJavascriptGuide.es6;
//ok
import AirbnbJavascriptGuide  from './AirbnbJavascriptGuide ';
export default AirbnbJavascriptGuide.es6;
//best
import {es6} from './AirbnbJavascriptGuide ';
export default es6;

忌用通配符import

//bad
import * as AirbnbJavascriptGuide from './AirbnbJavascriptGuide ';
//good
import AirbnbJavascriptGuide from './AirbnbJavascriptGuide ';

别在import时同时export

//bad
export { es6 as default } from './AirbnbJavascriptGuide ';
//good
import { es6 } from './AirbnbJavascriptGuide ';
export default es6;

同一个地址放在一个import

//bad 
import foo form 'foo';
...
import { name,age } from 'foo';
//good
import foo,{ name,age } form 'foo';
//best
import foo,{ 
            name,
            age 
            } form 'foo';

只有一个export时 用export default

//bad
export function foo() {}
//good
export default foo() {}

不要在import时用Webpack loader

//bad
import foo from  'css!sass!foo.scss';
//good
import foo from 'foo.css';

迭代遍历

用map、every、filter,find,findIndex,some,reduce等代替for-in,for-of

let numbers = [1,2,3,4]
//bad
let sum = 0;
for(let num of numbers){
    sum += num;
}    
//good
let sum = 0;
numbers.forEach(num => sum += num);

//bad
let increaseByOne = [];
for(let i = 0;i< numbers.length;i++){
    increaseByOne .push(numbers[i]+1);
}
//good
let increaseByOne = numbers.map(num => num + 1);

正确的constructor的书写

//good
let  test = function* (){
    //...
}

属性

通过.访问属性

let  luke = {
    jedi:true,
    age:28
}
//bad
let isJedi = luke['jedi'];
//good
let isJedi = luke.jedi;

通过变量访问属性时使用中括号 []

let  luke = {
    jedi:true,
    age:28
}
function getProp(prop) {
    return luke[prop];
}
let isJedi = getProp('jedi')

##变量##

用let和const声明变量

//good
let superPower = new SuperPower();

提升

var 声明会被提升至该作用域的顶部,但它们赋值不会提升

//bad
// 由于变量提升的原因,
// 在引用变量后再声明变量是可以运行的。
// 注:变量的赋值 `true` 不会被提升。
function example() {
  console.log(declaredButNotAssigned); // => undefined
  var declaredButNotAssigned = true;
}

匿名函数表达式的变量名会被提升,但函数内容并不会

function example() {
  console.log(anonymous); // => undefined

  anonymous(); // => TypeError anonymous is not a function

  var anonymous = function() {
    console.log('anonymous function expression');
  };
}    

函数声明的名称和函数体都会被提升

function example() {
  superPower(); // => Flying

  function superPower() {
    console.log('Flying');
  }
} 

比较和等号

优先使用 === 和 !== 而不是 == 和 !=

//good
if(a===1){}

使用简写

// bad
if (name !== '') {
  // ...stuff...
}

// good
if (name) {
  // ...stuff...
}

// bad
if (collection.length > 0) {
  // ...stuff...
}

// good
if (collection.length) {
  // ...stuff...
}

三元运算符通写在一行

// bad

const foo = maybe1 > maybe2
  ? "bar"
  : value1 > value2 ? "baz" : null;

// split into 2 separated ternary expressions
const maybeNull = value1 > value2 ? 'baz' : null;

// better
const foo = maybe1 > maybe2
  ? 'bar'
  : maybeNull;

// best
const foo = maybe1 > maybe2 ? 'bar' : maybeNull;   

避免不必要的三元运算符

// bad
const foo = a ? a : b;
const bar = c ? true : false;
const baz = c ? false : true;

// good
const foo = a || b;
const bar = !!c;
const baz = !c;

混合运算时,尽量用括号,易懂

//bad
if(a || b && c){
    //...
}
//good
if(a || (b && c)){
    //...
}

代码块

用大括号包裹所有的多行代码块

// bad
if (test)
  return false;
// good
if (test){
  return false; 
}

条件语句

条件语句,换行将运算符放在最前面

// bad

if ((foo === 123 || bar === 'abc') && doesItLookGoodWhenItBecomesThatLong() && isThisReallyHappening()) {
  thing1();
}
//good
if (
    (foo === 123 || bar === 'abc') 
    && doesItLookGoodWhenItBecomesThatLong() 
    && isThisReallyHappening()
    ) {
  thing1();
}

注释

- 使用 /** ... */ 作为多行注释
- 使用 // 作为单行注释 ,上方空一行
- 使用 // FIXME: 标注问题
- 使用 // TODO: 标注问题的解决方式

逗号

- 行首逗号:不需要
- 结尾的逗号: 需要

分号

- 别省略分号

类型转换

字符串

// bad
const totalScore = new String(this.reviewScore); // typeof totalScore is "object" not "string"

// bad
const totalScore = this.reviewScore + ''; // invokes this.reviewScore.valueOf()

// bad
const totalScore = this.reviewScore.toString(); // isn’t guaranteed to return a string

// good
const totalScore = String(this.reviewScore);

数字

let inputValue= 4;

// bad
const val = new Number(inputValue);

// bad
const val = +inputValue;

// bad
const val = inputValue >> 0;

// bad
const val = parseInt(inputValue);

// good
const val = Number(inputValue);

// good
const val = parseInt(inputValue, 10);

布尔

const age = 0;

// bad
const hasAge = new Boolean(age);

// good
const hasAge = Boolean(age);

// good
const hasAge = !!age;    

命名规则

- 避免单字母命名。命名应具备描述性
- 使用驼峰式命名对象、函数和实例
- 使用ES6命名构造函数或类
class  User {
    constructor(options) {
        this.name = options.name;
    }
}
let good = new User({
    name:"yup"
});
- 使用下划线 _ 开头命名私有属性
- 使用箭头函数避免this引用错误
//bad 
function test(){
    let self = this;
    return function(){
        console.log(self);
    }
}
//good
function test(){
    return ()=>{
        console.log(this);
    }
}
- 文件只输出一个类,文件名必须和类名完全保持一致
// file contents
class CheckBox {
  // ...
}
export default CheckBox;

// in some other file
// bad
import CheckBox from './checkBox';

// bad
import CheckBox from './check_box';

// good
import CheckBox from './CheckBox';

存取器

- 使用好get、set
- is、has
- 保持一致
// bad
dragon.age();

// good
dragon.getAge();
// bad
if (!dragon.age()) {
  return false;
}

// good
if (!dragon.hasAge()) {
  return false;
}

事件

// 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
});

jQuery

使用 $ 作为存储 jQuery 对象的变量名前缀

// bad
const sidebar = $('.sidebar');

// good
const $sidebar = $('.sidebar');

缓存 jQuery 查询

const $sidebar = $('.sidebar');

对 DOM 查询使用层叠

$('.sidebar ul')
$('.sidebar > ul')

对有作用域的 jQuery 对象查询使用 find

// bad
$('ul', '.sidebar').hide();
// good
$sidebar.find('ul').hide();


参考:
https://github.com/airbnb/javascript


dada86
993 声望22 粉丝

多努力一点点。