如何讓你的JavaScript程式碼更加語義化

Barret Lee發表於2014-08-27

語義化這個詞在 HTML 中用的比較多,即根據內容的結構化選擇合適的標籤。其作用不容小覷:

  • 賦予標籤含義,讓程式碼結構更加清晰,雖然我們可以在標籤上新增 class 來標識,但這種透過屬性來表示本體的形式會顯得不夠直接,而且在一定程度上也有冗餘。
  • 最佳化搜尋引擎(SEO),結構良好的網頁對搜尋引擎的親和力是很高的,百度和 google 也給出了很多網頁結構化的建議(規範),方便他們抓取網頁。
  • 利於裝置解析,如盲人閱讀器對頁面的分析,目前淘寶很多網頁都是支援盲人閱讀的,這種體驗上的最佳化得利於網頁的良好結構和語義化表達。
  • 便於開發者維護,在參加工作之前,很多程式設計師都是單人開發模式,單人開發無所謂程式碼結構,自己看得懂就差不多了,一旦走向工作崗位,會發現,以前的鄙習有點讓自己捉襟見肘了。

W3C Group 工作組在 web 規範上持續貢獻,他們的目標也是期望整個網際網路的發展態勢穩定統一起來。不扯遠了,回到本文需要闡述的重點:如何語義化 JavaScript 程式碼?

一、先看看那些不易讀懂的 JavaScript 程式碼

1. 判斷

// 資料型別判斷
if(Object.prototype.toString.call(str) === “[object String]”){
    // doSomething();
};

// 檔案型別判斷
if(/.*\.css(?=\?|$)/.test(“/path/to/main.css”)){
    // doSomething();
}

2. 清空一個佇列

var Queue = ["test1", "test2", "test3"];
// 常見方式
Queue.length = 0;
Queue = []; 

3. 註冊一個變數

// 註冊
var repos = {};

repos[“a”] = {
   name: “a”,
   content: {}
};

repos[“b”] = {
   name: “b”,
   content: {}
};

上面幾個例子倒不至於看不懂,程式都特別簡單,第一個例子中,我們透過 Object 原型鏈上的 toString 方法來判斷一個變數是否為 string 型別,以及使用正則來判斷一個檔案是不是 css 檔案。程式碼寫起來比較輕鬆,倘若我們同時需要判斷多個物件是否為多個型別中的一種呢?再比如我們需要在一串程式碼中提取 require 依賴關係呢,是否應該思考下如何組織自己的程式碼?

在第二個例子中,將陣列的長度設定為 0,或者使用空陣列來重置這個變數,都是十分常見的方式,但目前的場景是清空一個佇列,我們是否可以使用更加語義化的形式來呈現?比如我們只需要清空該佇列的前五個和後三個 item 呢?

第三個例子中,變數的註冊,把一堆註冊放在一起,上面的形式確實也是一目瞭然,如果 a b c d 等都是分隔穿插在幾百行程式碼之間呢?突然來個 repos["x"] 這樣是否顯得有些不太直觀。

為了說明本文所倡導的思想,上面的幾個解釋都有些含糊和牽強,請往下看。

二、提高程式碼語義性

針對上述三個案例,用更加語義化的方式來呈現程式碼:

1. 語義化變數

// 型別判斷
function isType(type){
    return function(o){
        return Object.prototype.toString.call(o) === '[object ' + type + ']';
    }
}

var isString = isType(“String”);
var isObject = isType("Object");
var isArray = isType("Array");
 
isString("I'm Barret Lee.");
isArray([1,2,3]);
isObject({});

我覺得不需要太多的解釋,對比

if(Object.prototype.toString.call(str) === “[object String]”){
    // code here...
}

顯得清新多了吧。

// 提取常量
var isCss = /.*\.css(?=\?|$)/;
isCss.test(“/path/to/main.css”);

不管 isCss 這個正則程式碼有多長,當我們看到 isCss 這個單詞就可以顧名思義。很多人寫正則都不會將正則單獨提取出來使用某個有意義的變數去儲存,加註釋還好,要是不加註釋,後續開發者就只能硬著頭皮看懂正則去理解程式碼的含義。

這樣的處理,實際上是增加了程式碼量,不過從工程角度去審視,有助於提高開發效率以及程式碼的組織性。

2. 語義化行為

var Queue = ["test1", "test2", "test3"];
Queue.splice(0, Queue.length);

上面程式碼具有很強的語義性,從索引為 0 的地方開始,直到佇列最後,刪除 Queue 中所有的 item。這種寫法的擴充套件性也更好:

Queue.splice(2, 4); // 刪除從索引為 2,往後的 4 個元素

這只是個小例子,有些行為是需要很多程式碼組合處理的,如果沒有很好的組合同一行為的程式碼,整個結構就顯得十分渙散,不利於閱讀。

// 註冊
var repos = [];

function register(o){
   repos[o.name] = o;
}

register({
  name: “a”,
  content: {}
});

對比我們之前

repos[“a”] = {
   name: “a”,
   content: {}
};

語義化程度是不是有所提高~

三、小結

程式碼的最佳化,需要考慮的維度很多。但是程式碼的最佳化並不是減少程式碼量,有的時候我們需要增加程式碼來提高程式碼的可閱讀性。

  • 正確標記變數
  • 封裝某個動作
  • 注意函式的寫法
  • 不容易理解的東西,加註釋

本文為拋磚引玉,希望可以觸發你對程式碼最佳化的敏感度的思考,寫出一手別人豎拇指的程式碼~

相關文章