語義化這個詞在 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: {}
};
語義化程度是不是有所提高~
三、小結
代碼的優化,需要考慮的維度很多。但是代碼的優化並不是減少代碼量,有的時候我們需要增加代碼來提高代碼的可閱讀性。
- 正確標記變量
- 封裝某個動作
- 注意函數的寫法
- 不容易理解的東西,加注釋
本文為拋磚引玉,希望可以觸發你對代碼優化的敏感度的思考,寫出一手別人豎拇指的代碼~