【译】js代码规范-最佳实践

原文地址:JavaScript Clean Code - Best Practices 原做者:Milos Proticjavascript


介绍

若是你关心代码的自己以及编写方式,而只是担忧代码是否有效的,你能够说你实践而且关心代码的规范性。专业的开发人员老是会考虑到本身便于未来还能可读和其余的团队人员,并非仅仅考虑到运行的结果。你写的任何代码并非只写一次,总会有其余的开发人员来作你写的代码,若是你写的不规范,而他则会痛苦不堪。但愿这我的不是你。java

整体来讲,规范性的代码能够定义为不言自明,易于人理解且易于更改或者扩展的编写方式。es6

当你接到别人写的代码,第一个印象就是“这个代码什么玩意儿”,那你问本身,你还会有多少次愿意继续作别人写的代码呢?编程

"WTF is that?"bash

"WTF did you do here?"编程语言

"WTF is this for?" (这个就不翻译了,本身感觉下)函数

下图就是表明以上所述内容的流行图片 post

image

自配的WTF表情包

引用Robert C.Martin的一句话,这话应该会让你思考编写方式。测试

Even bad code can function. But if the code isn’t clean, it can bring a development organization to its knees.ui

在本文中,重点将在于js,这些原则也能用于其余的编程语言。

一、强类型检查 === 代替 ==

0 == false // true
0 === false // false
2 == "2" // true
2 === "2" // false

// 例子
const value = "500";
if (value === 500) {
  console.log(value);
  // 没打印出来
}

if (value === "500") {
  console.log(value);
  // 打印出来了
}
复制代码

二、变量

  • 给变量命名时,应该要使变量名具备表明意图的象征,令人易于搜索而且容易理解。

Bad:

let daysSLV = 10;
let y = new Date().getFullYear();

let ok;
if (user.age > 30) {
  ok = true;
}
//本人解释:y,ok这些什么玩意儿呢,30又是什么意思呢?
复制代码

Good:

const MAX_AGE = 30; //哦,是最大的年龄
let daysSinceLastVisit = 10;
let currentYear = new Date().getFullYear();//哦,是当前年份

...

const isUserOlderThanAllowed = user.age > MAX_AGE;
复制代码
  • 不要在变量名中增长不必额外的单词

Bad:

let nameValue;
let theProduct;
复制代码

Good:

let name;
let product;
复制代码
  • 不要强制记忆变量名的上下文

Bad:

const users = ["John", "Marco", "Peter"];
users.forEach(u => {
  doSomething();
  doSomethingElse();
  // ...
  // ...
  // ...
  // ...
  // 这u什么玩意儿呢?
  register(u);
});
复制代码

Good:

const users = ["John", "Marco", "Peter"];
users.forEach(user => {
  doSomething();
  doSomethingElse();
  // ...
  // ...
  // ...
  // ...
  register(user);
});
复制代码
  • 变量名不要加上下文重复的单词

Bad:

const user = {
  userName: "John",
  userSurname: "Doe",
  userAge: "28"
};

...

user.userName;
复制代码

Good:

const user = {
  name: "John",
  surname: "Doe",
  age: "28"
};

...

user.name;
复制代码

三、函数

  • 函数名应该是动词或者短语,表明某种行为,描述它们在作什么

Bad:

function notif(user) {
  // implementation
}
复制代码

Good:

function notifyUser(emailAddress) {
  // implementation
}
复制代码
  • 避免使用大量的参数,理想的状况就是用两个或者更少的参数。参数越少,测试就越容易

Bad:

function getUsers(fields, fromDate, toDate) {
  // implementation
}
复制代码

Good:

function getUsers({ fields, fromDate, toDate }) {
  // implementation
}

getUsers({
  fields: ['name', 'surname', 'email'],
  fromDate: '2019-01-01',
  toDate: '2019-01-18'
}); 
复制代码
  • 函数应该使用默认参数,而不是条件语句

Bad:

function createShape(type) {
  const shapeType = type || "cube";
  // ...
}
复制代码

Good:

function createShape(type = "cube") {
  // ...
}
复制代码

(这个的缘由,可能有些人不明白的,在此放连接阮一峰es6入门-函数参数的默认值

  • 一个函数应该作一件事,避免在一个函数中执行多个操做。

Bad:

function notifyUsers(users) {
  users.forEach(user => {
    const userRecord = database.lookup(user);
    if (userRecord.isVerified()) {
      notify(user);
    }
  });
}
复制代码

Good:

function notifyVerifiedUsers(users) {
  users.filter(isUserVerified).forEach(notify);
}

function isUserVerified(user) {
  const userRecord = database.lookup(user);
  return userRecord.isVerified();
}
复制代码
  • 使用Object.assign设置默认对象。

Bad:

const shapeConfig = {
  type: "cube",
  width: 200,
  height: null
};

function createShape(config) {
  config.type = config.type || "cube";
  config.width = config.width || 250;
  config.height = config.width || 250;
}

createShape(shapeConfig);
复制代码

Good:

const shapeConfig = {
  type: "cube",
  width: 200
  // Exclude the 'height' key
};

function createShape(config) {
  config = Object.assign(
    {
      type: "cube",
      width: 250,
      height: 250
    },
    config
  );

  ...
}

createShape(shapeConfig);
复制代码
  • 不要使用标志记做为参数,由于它们告诉你该函数正在作的比它应该作的更多。

Bad:

function createFile(name, isPublic) {
  if (isPublic) {
    fs.create(`./public/${name}`);
  } else {
    fs.create(name);
  }
}
复制代码

Good:

function createFile(name) {
  fs.create(name);
}

function createPublicFile(name) {
  createFile(`./public/${name}`);
}
复制代码
  • 不要污染全局变量。若是须要扩展示有对象,请使用ES6类和继承,而不是在现有对象的原型链上建立函数

Bad:

Array.prototype.myFunc = function myFunc() {
  // implementation
};
复制代码

Good:

class SuperArray extends Array {
  myFunc() {
    // implementation
  }
}
复制代码

四、条件语句

  • 避免负面条件

Bad:

function isUserNotBlocked(user) {
  // implementation
}

if (!isUserNotBlocked(user)) {
  // implementation
}
复制代码

Good:

function isUserBlocked(user) {
  // implementation
}

if (isUserBlocked(user)) {
  // implementation
}
复制代码
  • 使用条件语句尽可能短点。这多是微不足道的,但值得一提。此方法仅用于布尔值,而且若是您肯定该值不是未定义的或为null。

Bad:

if (isValid === true) {
  // do something...
}

if (isValid === false) {
  // do something...
}
复制代码

Good:

if (isValid) {
  // do something...
}

if (!isValid) {
  // do something...
}
复制代码
  • 尽量避免switch分支,请改用多态和继承。

Bad:

class Car {
  // ...
  getMaximumSpeed() {
    switch (this.type) {
      case "Ford":
        return this.someFactor() + this.anotherFactor();
      case "Mazda":
        return this.someFactor();
      case "McLaren":
        return this.someFactor() - this.anotherFactor();
    }
  }
}
复制代码

Good:

class Car {
  // ...
}

class Ford extends Car {
  // ...
  getMaximumSpeed() {
    return this.someFactor() + this.anotherFactor();
  }
}

class Mazda extends Car {
  // ...
  getMaximumSpeed() {
    return this.someFactor();
  }
}

class McLaren extends Car {
  // ...
  getMaximumSpeed() {
    return this.someFactor() - this.anotherFactor();
  }
}
复制代码

五、Es6类

  • 类是JavaScript中的新语法糖,跟原型对象同样,只是它如今看起来不一样,你应该更喜欢它们而不是ES5的使用构造函数。

Bad:

const Person = function(name) {
  if (!(this instanceof Person)) {
    throw new Error("Instantiate Person with `new` keyword");
  }

  this.name = name;
};

Person.prototype.sayHello = function sayHello() { /**/ };

const Student = function(name, school) {
  if (!(this instanceof Student)) {
    throw new Error("Instantiate Student with `new` keyword");
  }

  Person.call(this, name);
  this.school = school;
};

Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
Student.prototype.printSchoolName = function printSchoolName() { /**/ };
复制代码

Good:

class Person {
  constructor(name) {
    this.name = name;
  }

  sayHello() {
    /* ... */
  }
}

class Student extends Person {
  constructor(name, school) {
    super(name);
    this.school = school;
  }

  printSchoolName() {
    /* ... */
  }
}
复制代码
  • 使用方法连接,许多库如jQuery和Lodash都使用这种模式。所以,您的代码将不那么冗长。在你的类中,只需在每一个函数的末尾返回它,你就能够将更多的类方法连接到它上面。

Bad:

class Person {
  constructor(name) {
    this.name = name;
  }

  setSurname(surname) {
    this.surname = surname;
  }

  setAge(age) {
    this.age = age;
  }

  save() {
    console.log(this.name, this.surname, this.age);
  }
}

const person = new Person("John");
person.setSurname("Doe");
person.setAge(29);
person.save();
复制代码

Good:

class Person {
  constructor(name) {
    this.name = name;
  }

  setSurname(surname) {
    this.surname = surname;
    // Return this for chaining
    return this;
  }

  setAge(age) {
    this.age = age;
    // Return this for chaining
    return this;
  }

  save() {
    console.log(this.name, this.surname, this.age);
    // Return this for chaining
    return this;
  }
}

const person = new Person("John")
    .setSurname("Doe")
    .setAge(29)
    .save();
复制代码

六、常规的避免

通常来讲,尽可能不要重复本身,就是说不该该编写重复的代码,也不要在你身后留下尾巴,好比未使用的函数和死代码。 因为各类缘由,你最终可能会有重复的代码。好比,你可能有两个略有不一样的东西,它们有许多共同之处,有时期限不足的迫使你建立包含几乎一样代码的单独函数。 关于死代码,这正如它的名字。它没有作任何事情,由于在某些开发阶段,你已经决定再也不用它,您应该在代码库中搜索这些不须要的函数和代码块并删除。 我建议你,一旦你决定再也不须要它,就立刻删除它, 以防你之后可能会忘记它的用途。 这只是改进代码所能作的小部分。 在我看来,这里所说的原则是人们常常不遵循的原则。 他们尝试但老是因各类缘由而没成功。 也许项目一开始时,代码是整洁干净,但在最后期限时,原则常常被忽略并转移到“TODO”或“REFACTOR”部分。 到那时,您的客户宁愿让您知足截止日期,而不是规范的代码。 到此为止! 感谢你阅读而且但愿在下一篇文章看到你。

相关文章
相关标签/搜索