看看这些被同事喷的JS代码风格你写过多少

做者:殷荣桧@腾讯

目录:

1、变量相关

2、函数相关

3、尽可能使用ES6,有能够能的话ES7中新语法

  如今写代码比之前好多了,代码的格式都有eslint,prettier,babel(写新版语法)这些来保证,然而,技术手段再高端都不能解决代码可读性(代码可否被将来的本身和同事看懂)的问题,由于这个问题只有人本身才能解决。咱们写代码要写到下图中左边这样基本上就功德圆满了。javascript

注:因为我的水平与眼界的缘由,这篇文章中并无彻底覆盖到常见的写代码的很差的习惯,因此你若是觉的有须要补充的,均可以在文章下方评论,或者直接到个人Github的这篇文章中评论。对于有用的,都将补充到个人掘金和Github中去。同时,你若是觉的文章写得还能够,Please在个人Github中送上你宝贵的Star,你的Star是我继续写文章最大的动力。vue

1、变量相关

(1)变量数量的定义java

NO:滥用变量:node

let kpi = 4;  // 定义好了以后再也没用过
function example() {
	var a = 1;
	var b = 2;
	var c = a+b;
	var d = c+1;
	var e = d+a;
	return e;
}
复制代码

YES: 数据只使用一次或不使用就无需装到变量中git

let kpi = 4;  // 没用的就删除掉,否则过三个月本身都不敢删,怕是否是那用到了
function example() {
	var a = 1;
	var b = 2;
	return 2*a+b+1;
}
复制代码

(2)变量的命名程序员

NO:自我感受良好的缩写github

let fName = 'jackie'; // 看起来命名挺规范,缩写,驼峰法都用上,ESlint各类检测规范的工具都经过,But,fName是啥?这时候,你是否是想说What are you 弄啥呢?
let lName = 'willen'; // 这个问题和上面的同样
复制代码

YES:无需对每一个变量都写注释,从名字上就看懂vuex

let firstName = 'jackie'; // 怎么样,是否是一目了然。少被喷了一次
  let lastName = 'willen';
复制代码

(3)特定的变量编程

NO:无说明的参数redux

if (value.length < 8) { // 为何要小于8,8表示啥?长度,仍是位移,仍是高度?Oh,my God!!
	....
}
复制代码

YES:添加变量

const MAX_INPUT_LENGTH = 8;
if (value.length < MAX_INPUT_LENGTH) { // 一目了然,不能超过最大输入长度
	....
}
复制代码

(4)变量的命名

NO:命名过于啰嗦

let nameString;
let theUsers;
复制代码

YES: 作到简洁明了

let name;
let users;
复制代码

(5)使用说明性的变量(即有意义的变量名)

NO:长代码不知道啥意思

const address = 'One Infinite Loop, Cupertino 95014';
const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
saveCityZipCode(
  address.match(cityZipCodeRegex)[1], // 这个公式到底要干吗,对不起,原做者已经离职了。本身看代码
  address.match(cityZipCodeRegex)[2], // 这个公式到底要干吗,对不起,原做者已经离职了。本身看代码
);
复制代码

YES:用变量名来解释长代码的含义

const address = 'One Infinite Loop, Cupertino 95014';
const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
const [, city, zipCode] = address.match(cityZipCodeRegex) || [];
saveCityZipCode(city, zipCode);
复制代码

(6)避免使用太多的全局变量

NO:在不一样的文件不停的定义全局变量

name.js
window.name = 'a';
hello.js
window.name = 'b';
time.js
window.name = 'c';  //三个文件的前后加载顺序不一样,都会使得window.name的值不一样,同时,你对window.name的修改了都有可能不生效,由于你不知道你修改过以后别人是否是又在别的说明文件中对其的值重置了。因此随着文件的增多,会致使一团乱麻。
复制代码

YES:少用或使用替代方案 你能够选择只用局部变量。经过(){}的方法。

若是你确实用不少的全局变量须要共享,你可使用vuex,redux或者你本身参考flux模式写一个也行。
复制代码

(7) 变量的赋值。

NO:对于求值获取的变量,没有兜底。

const MIN_NAME_LENGTH = 8;
let lastName = fullName[1];
if(lastName.length > MIN_NAME_LENGTH) { // 这样你就给你的代码成功的埋了一个坑,你有考虑过若是fullName = ['jackie']这样的状况吗?这样程序一跑起来就爆炸。要不你试试。
    ....
}
复制代码

YES:对于求值变量,作好兜底。

const MIN_NAME_LENGTH = 8;
let lastName = fullName[1] || ''; // 作好兜底,fullName[1]中取不到的时候,不至于赋值个undefined,至少还有个空字符,从根本上讲,lastName的变量类型仍是String,String原型链上的特性都能使用,不会报错。不会变成undefined。
if(lastName.length > MIN_NAME_LENGTH) {
    ....
}
其实在项目中有不少求值变量,对于每一个求值变量都须要作好兜底。
let propertyValue = Object.attr || 0; // 由于Object.attr有可能为空,因此须要兜底。
可是,赋值变量就不须要兜底了。
let a = 2; // 由于有底了,因此不要兜着。
let myName = 'Tiny'; // 由于有底了,因此不要兜着。
复制代码

2、函数相关

(1)函数命名

NO:从命名没法知道返回值类型

function showFriendsList() {....} // 如今问,你知道这个返回的是一个数组,仍是一个对象,仍是true or false。你能答的上来否?你能答得上来我请你吃松鹤楼的满汉全席还请你不要当真。
复制代码

Yes: 对于返回true or false的函数,最好以should/is/can/has开头

function shouldShowFriendsList() {...}
function isEmpty() {...}
function canCreateDocuments() {...}
function hasLicense() {...}
复制代码

(2) 功能函数最好为纯函数

NO: 不要让功能函数的输出变化无常。

function plusAbc(a, b, c) {  // 这个函数的输出将变化无常,由于api返回的值一旦改变,一样输入函数的a,b,c的值,但函数返回的结果却不必定相同。
		var c = fetch('../api');
		return a+b+c;
}
复制代码

YES:功能函数使用纯函数,输入一致,输出结果永远惟一

function plusAbc(a, b, c) {  // 一样输入函数的a,b,c的值,但函数返回的结果永远相同。
		return a+b+c;
}
复制代码

(3)函数传参

NO:传参无说明

page.getSVG(api, true, false); // true和false啥意思,一目不了然
复制代码

YES: 传参有说明

page.getSVG({
	imageApi: api,
	includePageBackground: true, // 一目了然,知道这些true和false是啥意思
	compress: false,
})
复制代码

(4)动做函数要以动词开头

NO: 没法辨别函数意图

function emlU(user) {
	....
}
复制代码

YES:动词开头,函数意图就很明显

function sendEmailToUser(user) {
    ....
}
复制代码

(5)一个函数完成一个独立的功能,不要一个函数混杂多个功能

这是软件工程中最重要的一条规则,当函数须要作更多的事情时,它们将会更难进行编写、测试、理解和组合。当你能将一个函数抽离出只完成一个动做,他们将可以很容易的进行重构而且你的代码将会更容易阅读。若是你严格遵照本条规则,你将会领先于许多开发者。

NO:函数功能混乱,一个函数包含多个功能。最后就像能以一当百的老师傅同样,被乱拳打死(乱拳(功能复杂函数)打死老师傅(老程序员))

function sendEmailToClients(clients) {
  clients.forEach(client => {
    const clientRecord = database.lookup(client)
    if (clientRecord.isActive()) {
      email(client)
    }
  })
}
复制代码

YES: 功能拆解,

function sendEmailToActiveClients(clients) {  //各个击破,易于维护和复用
  clients.filter(isActiveClient).forEach(email)
}

function isActiveClient(client) {
  const clientRecord = database.lookup(client)
  return clientRecord.isActive()
}
复制代码

(6)优先使用函数式编程

NO: 使用for循环编程

for(i = 1; i <= 10; i++) { // 一看到for循环让人顿生不想看的情愫
   a[i] = a[i] +1;
}
复制代码

YES:使用函数式编程

let b = a.map(item => ++item) // 怎么样,是否是很好理解,就是把a的值每项加一赋值给b就能够了。如今在javascript中几乎全部的for循环均可以被map,filter,find,some,any,forEach等函数式编程取代。
复制代码

(7) 函数中过多的采用if else ..

No: if else过多

if (a === 1) {
	...
} else if (a ===2) {
	...
} else if (a === 3) {
	...
} else {
   ...
}
复制代码

YES: 可使用switch替代或用数组替代

switch(a) {
   case 1:
   	    ....
   case 2:
   		....
   case 3:
   		....
  default:
   	....
}
Or
let handler = {
    1: () => {....},
    2: () => {....}.
    3: () => {....},
    default: () => {....}
}

handler[a]() || handler['default']()
复制代码

3、尽可能使用ES6,有能够能的话ES7中新语法(只罗列最经常使用的新语法,说实话,有些新语法不怎么经常使用)

(1)尽可能使用箭头函数

NO:采用传统函数

function foo() {
  // code
}
复制代码

YES:使用箭头函数

let foo = () => {
  // code
}
复制代码

(2)链接字符串

NO:采用传统+号

var message = 'Hello ' + name + ', it\'s ' + time + ' now'
复制代码

YES:采用模板字符

var message = `Hello ${name}, it's ${time} now`
复制代码

(3) 使用解构赋值

NO:使用传统赋值:

var data = { name: 'dys', age: 1 };
var name = data.name;
var age = data.age;

var fullName = ['jackie', 'willen'];
var firstName = fullName[0];
var lastName = fullName[1];
复制代码

YES:使用结构赋值:

const data = {name:'dys', age:1};
const {name, age} = data;   // 怎么样,是否是简单明了

var fullName = ['jackie', 'willen'];
const [firstName, lastName] = fullName;
复制代码

(4) 尽可能使用类class

NO: 采用传统的函数原型链实现继承

典型的 ES5 的类(function)在继承、构造和方法定义方面可读性较差,当须要继承时,优先选用 class。代码太多,就省略了。
复制代码

YES:采用ES6类实现继承

class Animal {
  constructor(age) {
    this.age = age
  }

  move() {
    /* ... */
  }
}

class Mammal extends Animal {
  constructor(age, furColor) {
    super(age)
    this.furColor = furColor
  }

  liveBirth() {
    /* ... */
  }
}

class Human extends Mammal {
  constructor(age, furColor, languageSpoken) {
    super(age, furColor)
    this.languageSpoken = languageSpoken
  }

  speak() {
    /* ... */
  }
}
复制代码

  先写到这了,这是目前为止发现的问题,这篇文章中并无彻底覆盖到常见的写代码的很差的习惯,因此你若是觉的有须要补充的,均可以在文章下方评论,或者直接到个人 Github的这篇文章中评论。对于有用的,都将补充到个人掘金和 Github中去。同时,你若是觉的文章写得还能够,Please在个人 Github中送上你宝贵的Star,你的Star是我继续写文章最大的动力。
注:除了上述这些人为习惯以外,就像前面提到的,对于机械性的,你可使用Babel、Eslint、Prettier这些工具来保证代码的格式一致。
复制代码

参考资料

blog.risingstack.com/javascript-… (JavaScript Clean Coding Best Practices)

www.zhihu.com/question/20… (如何写出优美的 JavaScript 代码?)

相关文章
相关标签/搜索