Airbnb JavaScript代码规范(二)

8.箭头函数

1) 当你需要用到匿名(anonynous)函数的时候,使用箭头函数。eslint:prefer-arrow-callback,arrow-saocing

它创建了一个在其上下文中执行的函数版本,这通常是您想要的,并且是一种更简洁的语法。如果你有一个相当复杂的函数,你可能会将这个逻辑移到它自己的命名函数表达式

//bad
[1,2,3].map(function k(x) {
 const y = x+1;
 return x*y;
});
//good
[1,2,3].map((x) => {
 cosnt y = x+1return x*y;
});

2)如果函数体由一个返回无副作用的表达式的单个语句组成,则省略大括号并使用隐式返回。否则,保留大括号并使用返回语句。

// bad
[1, 2, 3].map(number => {
  const nextNumber = number + 1;
  `A string containing the ${nextNumber}.`;
});

// good
[1, 2, 3].map(number => `A string containing the ${number}.`);

// good
[1, 2, 3].map((number) => {
  const nextNumber = number + 1;
  return `A string containing the ${nextNumber}.`;
});

// good
[1, 2, 3].map((number, index) => ({
  [index]: number,
}));

// No implicit return with side effects
function foo(callback) {
  const val = callback();
  if (val === true) {
    // Do something if callback returns true
  }
}

let bool = false;

// bad
foo(() => bool = true);

// good
foo(() => {
  bool = true;
});

3)如果表达式跨越多行,请将其包装在括号中以提高可读性。

// bad
['get', 'post', 'put'].map(httpMethod => Object.prototype.hasOwnProperty.call(
    httpMagicObjectWithAVeryLongName,
    httpMethod,
  )
);

// good
['get', 'post', 'put'].map(httpMethod => (
  Object.prototype.hasOwnProperty.call(
    httpMagicObjectWithAVeryLongName,
    httpMethod,
  )
));

4) 如果你的函数只有一个参数,并且不使用大括号,则省略括号。否则,为了清晰和一致,总是在参数周围加括号。注意:始终使用括号也是可以接受的,在这种情况下,eslint使用“always”选项。

//bad
[1,2,3].map((x) => x * x);
//good
[1,2,3].map(x => x * x);
//good
[1,2,3].map(number => (
 `A long string with the ${number}.It's so long that we don't want it to take up space on the .map line!`
));
//bad
[1,2,3].map(x => {
 const y = x + 1;
 return x * y;
});
//good
[].map((x) => {
 const y = x + 1;
 return x * y;
});

5)避免使用比较运算符(<=,> =)混淆箭头函数语法(=>)。

//bad
const itemHeight = item => item.height >256 ? item.largeSize : item.smallSize;
//good (1) 跟箭头分行显示,避免混淆
const itemHeigth = (item) => {
 const { heigth,largeSize,smallSize } = item;
 return height > 256 ? largeSize : smallSize;
}
//good (2) 用括号包装起来
const itemHeight = item => (item.height> 256 ? item.largeSize : item.smallSize);

6)使用隐式返回来强化箭头函数体的位置。.

//bad
(foo) => 
 bar;

(foo) => 
 (bar);

//good
(foo) => bar;
(foo) => (bar);
(foo) => (
 bar
);

9.类classes和构造函数Constructors

1) 总是使用class,避免直接操作prototype

class语法更简洁,更容易推理。

//bad
function Queue(contents = []){
 this.queue = [...contents];
}
Queue.prototye.pop = function () {
 const value = this.queue[0];
 this.queue.splice(0,1);
 return value;
}

//good
class Queue {
 constructor(contents = []){
  this.queue = [...contents];
 }
 pop() {
  const value = this.queue[0];
  this.queue.splice(0,1);
  return value;
 }
}

2) 使用extends来继承

它是继承原型功能而不破坏instanceof的内置方式。

//bad
const inherits = require('inherits');
function PeekableQueue(contents) {
 Queue.apply(this,contents);
}
inherits(PeekableQueue,Queue);
PeekableQueue.prototype.peek = function () {
 return this.queue[0];
};

//good
class PeekaleQueue extends Queue {
 peek() {
 return this.queue[0];
 }
}

3) 方法返回this,以便于方法链式调用。

//bad
Jedi.prototye.jump = function () {
 this.jumping = true;
 return true;
};
Jedi.prototype.setHeight = function (height){
 this.height = height;
};
const luke = new Jedi();
luke.jump();//=>true
luke.setHeight(20);//=>undefined

//good
class Jedi {
 jump() {
  this.jumping = true;
  return this;
 }
 setHeight(height) {
  this.height = height;
  return this;
 }
}

const luke = new Jedi();
luke.jump()
    .setHeight(20);

4) 自定义toString()方法,确保它成功运行并且没有副作用。

class Jedi {
 constructor(options = {}) {
  this.name = options.name || 'no name';
 }
 getName() {
  return this.name;
 }
 toString() {
  return `Jedi - ${this.getName()}`;
 }
}

5) 如果没有指定,则类具有默认构造函数。一个空的构造函数或者只是委托给一个父类是不必要的。

//bad 
class Jedi {
 constructor() {}
 getName() {
  return this.name;
 }
}
//bad 
class Rey extends Jedi {
 constructor(...args){
  super(...args);
 }
}

//good
class Rey  extends Jedi {
 cosntructor(..args) {
  super(...args);
  this.name = 'Rey';//除了super,还有其他的代码
 }
}

6) 避免重复类的成员

//bad
class Foo {
 bar() { return 1; }
 bar() { return 2; }//重复了类的成员bar
}
//good
class Foo {
 bar() { return 1; }
}
//good
class Boo {
 bar() { return 2; }
}

10.模块

1) 始终使用模块import/export优先于非标准模块系统方法,你可以传输到那你首选的模块系统。
模块就是将来啊!

//bad
const AirbnbStyleGuide = require('./AirbnbStyleGuide');
module.exports = AirbnbStyleGuide.es6;

//ok
import AirbnbStyleGuide from './AirbnbStyleGuide';
export default AirbnbStyleGuide.es6;

//best
import { es6 } from './AirbnbStyleGuide';
export default es6;

2) 不要使用通配符*进行import。

如果使用了通配符导入的话,我们导出的时候就只有一种方式了,很局限。

import * as AirbnbStyleGuide from './AirbnbStyleGuide';
//good
import AirbnbStyleGuide from './AirbnbStyleGuide'

3) 不要从导入的地方直接导入

//bad 
export { es6 as default } from './AirbnbStyleGuide'

//good
import { es6 } from './AirbnbStyleGuide';
export default es6;

4) 在同一个地方,同一条路径只导入一次。

//bad
import foo from 'foo';
import { named1,named2 } from 'foo';

//good 
import foo,{ named1,named2 } from 'foo';

//good
import foo,{
 named1,
 named2
} from 'foo'

5) 不要导出可变的变量

//bad
let foo = 3;
export { foo };//let可以修改值

//good
const foo = 3;
export { foo };

6) 在只需要导出一个模块时,首选默认导出,优先于命名导出。
鼓励一个文件只导出一个东西,因为更容易维护,可读性更强。

//bad
export function foo() {}

//good 
export default function foo() {}

7)

你可能感兴趣的:(Javascript)