摘要:壞的命名方式好的命名方式避免使用過多參數。你只需要在每一個函數的末尾返回,之后的代碼會更加的簡潔。在很多情況下,你可能搞出重復代碼。自從年雙十一正式上線,累計處理了億錯誤事件,付費客戶有金山軟件百姓網等眾多品牌企業。
譯者按: 簡潔的代碼可以避免寫出過多的BUG。
原文: JavaScript Clean Code - Best Practices
譯者: Fundebug
本文采用意譯,版權歸原作者所有
引文作為一個開發者,如果你關心代碼質量,除了需要認真測試代碼能否正確執行以外,還要注重代碼的整潔(clean code)。一個專業的開發者會從將來自己或則他人方便維護的角度考慮如何寫代碼,而不僅僅是機器能夠讀懂。你寫的任何代碼有很大幾率會被再次重構,希望未來重構代碼的那個人不會覺得這是一場災難。
代碼的簡潔之道可以被理解為:代碼自我解釋(且注釋少),開發者友好(易于理解,修改和擴展)。
想想之前閱讀別人的代碼的時候,說過多少次下面的話?
"WTF is that?""WTF did you do here?"
"WTF is this for?"
下面這張圖很形象地描述了這個情況:
《Clean Code》的作者Robert C. Martin (Uncle Bob) 說過這樣的話.
雖然爛代碼可以運行,但是它不夠整潔,它會把整個開發團隊給整跪了
本文主要講 JavaScript 代碼的整潔之道。
1. 強類型檢查建議使用 === 而不是 == 來判斷是否相等
// 如果沒有妥善處理的話,可能會出現和預想不一樣的結果 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); }2. 變量命名
變量命名盡量直觀易懂,方便查找;而且其他開發者也容易理解。
不好的命名方式:
let daysSLV = 10; let y = new Date().getFullYear(); let ok; if (user.age > 30) { ok = true; }
好的命名方式:
const MAX_AGE = 30; let daysSinceLastVisit = 10; let currentYear = new Date().getFullYear(); ... const isUserOlderThanAllowed = user.age > MAX_AGE;
不要使用多余的無意義的單詞來組合命名
壞的命名方式:
let nameValue; let theProduct;
好的命名方式:
let name; let product;
不要使用無意義的字符/單詞來命名,增加額外的記憶負擔
壞的命名方式:
const users = ["John", "Marco", "Peter"]; users.forEach(u => { doSomething(); doSomethingElse(); // ... // ... // ... // ... // 這里u到底指代什么? register(u); });
好的命名方式:
const users = ["John", "Marco", "Peter"]; users.forEach(user => { doSomething(); doSomethingElse(); // ... // ... // ... // ... register(user); });
在某些環境下,不用添加冗余的單詞來組合命名。比如一個對象叫user,那么其中的一個名字的屬性直接用name,不需要再使用username了。
壞的命名方式:
const user = { userName: "John", userSurname: "Doe", userAge: "28" }; ... user.userName;
好的命名方式:
const user = { name: "John", surname: "Doe", age: "28" }; ... user.name;3. 函數
請使用完整的聲明式的名字來給函數命名。比如一個函數實現了某個行為,那么函數名可以是一個動詞或則一個動詞加上其行為的被作用者。名字就應該表達出函數要表達的行為。
壞的命名方式:
function notif(user) { // implementation }
好的命名方式:
function notifyUser(emailAddress) { // implementation }
避免使用過多參數。最好一個函數只有 2 個甚至更少的參數。參數越少,越容易做測試。
壞的使用方式:
function getUsers(fields, fromDate, toDate) { // implementation }
好的使用方式:
function getUsers({ fields, fromDate, toDate }) { // implementation } getUsers({ fields: ["name", "surname", "email"], fromDate: "2019-01-01", toDate: "2019-01-18" });
為函數參數設置默認值,而不是在代碼中通過條件判斷來賦值。
壞的寫法:
function createShape(type) { const shapeType = type || "cube"; // ... }
好的寫法:
function createShape(type = "cube") { // ... }
一個函數應該只做一件事情。避免將多個事情塞到一個函數中。
壞的寫法:
function notifyUsers(users) { users.forEach(user => { const userRecord = database.lookup(user); if (userRecord.isVerified()) { notify(user); } }); }
好的寫法:
function notifyVerifiedUsers(users) { users.filter(isUserVerified).forEach(notify); } function isUserVerified(user) { const userRecord = database.lookup(user); return userRecord.isVerified(); }
使用Objecg.assign來設置默認對象值。
壞的寫法:
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);
好的寫法:
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);
不要使用 true/false 的標簽(flag),因為它實際上讓函數做了超出它本身的事情。
壞的寫法:
function createFile(name, isPublic) { if (isPublic) { fs.create(`./public/${name}`); } else { fs.create(name); } }
好的寫法:
function createFile(name) { fs.create(name); } function createPublicFile(name) { createFile(`./public/${name}`); }
不要污染全局。如果你需要對現有的對象進行擴展,不要在對象的原型鏈上定義函數。請使用 ES 的類和繼承。
壞的寫法:
Array.prototype.myFunc = function myFunc() { // implementation };
好的寫法:
class SuperArray extends Array { myFunc() { // implementation } }
好的代碼風格可以避免不小心寫出有BUG的代碼,以防萬一,推薦使用Fundebug做線上實時BUG監控!
4. 判斷條件避免使用否定的條件。
壞的寫法:
function isUserNotBlocked(user) { // implementation } if (!isUserNotBlocked(user)) { // implementation }
好的寫法:
function isUserBlocked(user) { // implementation } if (isUserBlocked(user)) { // implementation }
使用簡短的條件。這個要求看上去簡單,但是值得提醒。
壞的寫法:
if (isValid === true) { // do something... } if (isValid === false) { // do something... }
好的寫法:
if (isValid) { // do something... } if (!isValid) { // do something... }
如果你很確定它的值不是undefined或則null,我建議你這么做。
盡量避免使用判斷條件,推薦說那個多態(polymorphism)或則繼承。
壞的寫法:
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(); } } }
好的寫法:
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(); } }5. ES 類
類是 JavaScript 新推出的語法糖。建議使用類而不是用老式的直接定義函數的寫法。
壞的寫法:
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() { /**/ };
好的寫法:
class Person { constructor(name) { this.name = name; } sayHello() { /* ... */ } } class Student extends Person { constructor(name, school) { super(name); this.school = school; } printSchoolName() { /* ... */ } }
使用函數調用鏈。像 jQuery,Lodash 都使用這個模式。你只需要在每一個函數的末尾返回this,之后的代碼會更加的簡潔。
壞的寫法:
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();
好的寫法:
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();6. 其它
總的來說,你不能寫重復代碼,不能留下一堆不再使用的函數,永遠不會執行的代碼(死代碼)。
在很多情況下,你可能搞出重復代碼。比如你要實現兩個略微不同的功能,他們有很多相通的地方,但是由于項目截止時間快到了,你不得不快速復制黏貼再稍微修改修改來實現。
對于死代碼,最好的做法就是你決定不再使用它的那一刻就把它刪掉。時間過去太久,你甚至會忘記自己當初為什么定義它。下面這幅圖很形象地描述了這個情況:
關于FundebugFundebug專注于JavaScript、微信小程序、微信小游戲、支付寶小程序、React Native、Node.js和Java線上應用實時BUG監控。 自從2016年雙十一正式上線,Fundebug累計處理了10億+錯誤事件,付費客戶有Google、360、金山軟件、百姓網等眾多品牌企業。歡迎大家免費試用!
版權聲明轉載時請注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2019/06/11/javascript-clean-code/
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/104604.html
摘要:那么,這次我們不妨試試,在不使用循環語句的情況下,如何編程呢示例數組元素求和數組如下使用循環語句可知,我們需要通過修改變量,來計算結果。 譯者按: 通過使用數組的reduce、filter以及map方法來避免循環語句。 原文: Coding Tip: Try to Code Without Loops 譯者: Fundebug 為了保證可讀性,本文采用意譯而非直譯。另外,本文版權歸...
摘要:的黑客與設計剖析設計之美的秘密,英文原版在這里,還有一套免費教程。的代碼整潔之道程序員的職業素養,英文原版的學習如何為他人寫文檔我們與同事或者其他人溝通的很大一部分都是通過文字來的。 作者:Artem Sapegin 編譯:胡子大哈 翻譯原文:http://huziketang.com/blog/posts/detail?postId=58aaa33bfc5b7f63e8c23f68...
摘要:編者按本文主要介紹通過與建立模塊。其中之一就是導入導出模塊的語法被整理為模塊處理的唯一方法。這可以作為依賴這個模塊的某個項目的一部分。創建并初始化這得花點時間。以用戶角度展示系統響應速度,以地域和瀏覽器維度統計用戶使用情況。 【編者按】本文主要介紹通過 ES7 與 Babel 建立 JavaScript 模塊。文章系國內 ITOM 管理平臺 OneAPM 工程師編譯呈現,以下為正文。 ...
摘要:代碼整潔之道整潔的代碼不僅僅是讓人看起來舒服,更重要的是遵循一些規范能夠讓你的代碼更容易維護,同時降低幾率。另外這不是強制的代碼規范,就像原文中說的,。里式替換原則父類和子類應該可以被交換使用而不會出錯。注釋好的代碼是自解釋的。 JavaScript代碼整潔之道 整潔的代碼不僅僅是讓人看起來舒服,更重要的是遵循一些規范能夠讓你的代碼更容易維護,同時降低bug幾率。 原文clean-c...
摘要:設計模式是以面向對象編程為基礎的,的面向對象編程和傳統的的面向對象編程有些差別,這讓我一開始接觸的時候感到十分痛苦,但是這只能靠自己慢慢積累慢慢思考。想繼續了解設計模式必須要先搞懂面向對象編程,否則只會讓你自己更痛苦。 JavaScript 中的構造函數 學習總結。知識只有分享才有存在的意義。 是時候替換你的 for 循環大法了~ 《小分享》JavaScript中數組的那些迭代方法~ ...
閱讀 4620·2021-10-25 09:48
閱讀 3212·2021-09-07 09:59
閱讀 2167·2021-09-06 15:01
閱讀 2693·2021-09-02 15:21
閱讀 2732·2019-08-30 14:14
閱讀 2184·2019-08-29 13:59
閱讀 2514·2019-08-29 11:02
閱讀 2533·2019-08-26 13:33