原文地址:JavaScript Clean Code - Best Practices 原做者:Milos Proticjavascript
若是你關心代碼的自己以及編寫方式,而只是擔憂代碼是否有效的,你能夠說你實踐而且關心代碼的規範性。專業的開發人員老是會考慮到本身便於未來還能可讀和其餘的團隊人員,並非僅僅考慮到運行的結果。你寫的任何代碼並非只寫一次,總會有其餘的開發人員來作你寫的代碼,若是你寫的不規範,而他則會痛苦不堪。但願這我的不是你。java
整體來講,規範性的代碼能夠定義爲不言自明,易於人理解且易於更改或者擴展的編寫方式。es6
當你接到別人寫的代碼,第一個印象就是「這個代碼什麼玩意兒」,那你問本身,你還會有多少次願意繼續作別人寫的代碼呢?編程
"WTF is that?"bash
"WTF did you do here?"編程語言
"WTF is this for?" (這個就不翻譯了,本身感覺下)函數
下圖就是表明以上所述內容的流行圖片 post
引用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();
}
複製代碼
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}`);
}
複製代碼
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
}
複製代碼
Bad:
if (isValid === true) {
// do something...
}
if (isValid === false) {
// do something...
}
複製代碼
Good:
if (isValid) {
// do something...
}
if (!isValid) {
// do something...
}
複製代碼
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類
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() {
/* ... */
}
}
複製代碼
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」部分。 到那時,您的客戶寧願讓您知足截止日期,而不是規範的代碼。 到此爲止! 感謝你閱讀而且但願在下一篇文章看到你。