從jQuery談庫與框架的設計之優劣


jQuery是業內知名的javascript框架,它的實現和設計可以說代表了javascript界最高的水平,本文試從四個方面來以jQuery為例總結庫與框架設計的原則和優劣判斷。

解決問題

首先請看一個我實現的框架,我把這個庫稱為四則運算。

function add(a,b) {
    return a+b;
}
function mul(a,b) {
    return a*b;
}
function minus(a,b) {
    return a-b;
}
function div(a,b) {
    return a/b;
}

這個庫的API簡潔優美,實現的更是優雅無比,它把四則運算統一成了函數形式,使得我們的開發更加方便。最強大的是,這個做法使得四則運算支持函數式編程,比如:

function acc(a,b,f) {
    var jieguo = a; //http://weibo.com/2178807082/zk1kOcMPU
    for(var i = 1; i<b; i++) {
        jieguo = f(jieguo,a);
    }
    return jieguo
}

這樣,通過acc函數,我們可以輕易實現n次方運算,這正是函數式編程之美。

舉這個例子是為了告訴大家,一個框架/庫其實可以不需要解決任何問題——只要你會亂用概念、自吹和哄騙新手就夠了。

下面我們來看看一個非常成功的框架——jQuery解決的問題,讓我們來看看jQuery首頁的"Brief Look"中給出的第一個例子。

DOM Traversal and Manipulation

$( "button.continue" ).html( "Next Step..." )

嗯,沒錯,jQuery希望幫助我們解決遍歷DOM的問題,如果沒有jQuery,我們大概要寫一個traversal函數了。

function traversal(node, f) {
    f(node);
    if(node.children.length) {
        for(var i = 0; i<node.children.length;i++)
            traversal(node.children[i],f);
    }
}

traversal(document.body,function(element){
    if(element.tagName=="button" && element.className.match(/continue/)) {
        element.innerHTML = "Next Step...";
    }
})

traversal這個函數真的是超麻煩不是么?竟然有175個字符呢!使用起來也有166個字符,用了jQuery之后,只要45個字符就可以搞定呢!好神奇!

好吧原諒我剛才把思維模式切換到了"write less, do more"模式,jQuery正是通過一個字符一個字符地節約程序員的工作量來達到這一偉大目標的。

壓縮后仍達97k的jQuery竟然幫助我們少寫了這么多代碼,好神奇啊啊啊!這正是庫/框架設計的要點,那就是"沒有問題創造問題也要解決問題!"

命名

命名問題對於庫/框架來說,尤其重要。

總的來說,如同正統程序員那樣追求命名的易讀、易懂、與原生一致的話,你的庫/框架不會有任何出彩的地方。

好的庫/框架,命名有幾個原則,第一個原則,就是要有厚重的歷史感。

在80年代,因為C語言支持的變量名最長為8字節,聰明的程序員們使用了一種縮寫方式,保留發音的輕輔音字母,省略元音字母和部分濁輔音字母。

比如:

  • button=>btn
  • text=>txt
  • search=>srch
  • fuck=>fk
  • click=>clk
  • double=>db

沒錯,這樣雖然省略了字母,但是英文好的人仍然可以讀出單詞來,而現在,雖然我們完全沒有這種需要,我們也可以為了給新人以距離感和絕對的震懾而使用這種命名。

還有一種歷史上的命名方式:匈牙利命名。

匈牙利命名使用簡寫的類型作為變量的前綴,比如

  • iCount表示int類型的count
  • szText表示字符串類型的text
  • bIsNumber表示布爾類型isNumber
  • dRate表示表示雙精度浮點類型rate

是不是看上去很酷?值得一提的是,sz表示以0結尾的字符串,這是C語言中字符串的實現方式,JS中完全不是這樣實現的字符串,所以這樣用可以大大提升你在新手中的地位,他們做夢也猜不到sz是字符串的意思。

另外,其實js是弱類型語言,變量根本就跟類型不是綁定的。

除了歷史之外,特殊符號也是我們的首選,在javascript中,$美元符號和_下划線是非常棒的選擇。這當中的代表作當屬jQuery和underscore.

jQuery的$使用也並非原創,先行者是prototype.js,這也讓jQuery的做法具有相當厚重的歷史感。同時,美元符號比下划線強的地方是,美元符號還具有吉祥如意的寓意,咱們寫代碼的,出來不就是混口飯吃,如果代碼經常出現美元,一定會給我們帶來很多財運的。

占領這些特殊符號可以讓別的框架無符號可用,當年jQuery和prototype.js爭霸之時,jQuery就被迫搞出來了noconflict——盡管基本沒見過有人用過,畢竟要把滿篇的$改成jQuery還是頗費體力的,多數人會選擇放棄一個庫。(什么你說根本不需要替換?直接在外面套個閉包就能解決問題?醒醒吧親,能同時用倆帶$庫的工程師怎么可能會那種高級玩意兒啊,人家都是實踐派好吧?)

不過大家不要傷心,雖然沒有了$和_可以搶,ES5為我們帶來了更多奇形怪狀的、鍵盤輕易都輸入不來的標示符可用字符。我首先要推薦的是兩個零寬字符<zwnj>和<zwj>,這倆字符一個是連接符,一個是非連接符,它們的厲害之處在於,不可見,通過這倆字符,你可以制造出假的$來。

請看以下代碼:

var $ = 1;

估計你做夢也想不到這變量其實是$\u200D(<zwj>)吧......

通過\u200D和\u200C的組合,可以制造神奇的代碼出來,你的用戶一定會交口稱贊你的魔法代碼的!

不止如此!更多奇怪的字符等你挖掘!

接口設計

除了命名,接口設計也是框架的核心之一。

那些平庸的框架會用"單一職責"原則來設計接口:不論是類還是函數,一個只做一件事,而且跟命名 中所說的完全一致。

Noooooooooooo ! 這也太無趣了!

我們來看看jQuery的$有多少種用法!摘自官方文檔:

  • jQuery( selector [, context ] )
  • jQuery( element )
  • jQuery( elementArray )
  • jQuery( object )
  • jQuery( jQuery object )
  • jQuery()
  • jQuery( html [, ownerDocument ] )
  • jQuery( html, attributes )
  • jQuery( callback )

沒錯!這個函數(jQuery就是)居然有9種重載!而且重載中最少包含了3種毫不相干的使用方法!一段時間里,我曾經在面試中問所有聲稱自己熟悉jQuery的面試者這個函數有多少種用法,可以答上三種以上的僅有1人,而沒有人答出來過超過5種!

可以說,$在jQuery使用者的眼里就是一個神!你能想到的事情它都能做!在可以預見的將來,相信jQuery會結合人工智能,做到不論你想實現任何功能,都只需要寫同樣的代碼:

$();

怎么樣,看清楚接口設計的原則了么?那就是:盡量把功能加到以前的接口上,通過加參數、區分參數類型來添加功能,不論它們有沒有聯系,也不論API的名稱是什么!哦...... 對了這個應該結合上文提到的命名,請使用沒有任何意義的魔法變量名!

耦合

你可能常常聽到一些舊時代的程序員講,程序必須"高內聚、低耦合"。然而,這個說法具有極大的誤導性。

我們先來看看jQuery的事件綁定:

var hiddenBox = $( "#banner-message" );
$( "#button-container button" ).on( "click", function( event ) {
  hiddenBox.show();
});

假如我不想使用選擇器,只想要綁定事件到一個DOM元素上怎么辦呢?答案是,你要首先把他變成一個jQuery對象才行

$(document.querySelector("#button-container button")).on( "click", function( event ) {
  hiddenBox.show();
});

接下來我們來看jQuery的ajax部分:

$.ajax({
  url: "/api/getWeather",
  data: {
    zipcode: 97201
  },
  success: function( data ) {
    $( "#weather-temp" ).html( "<strong>" + data + "</strong> degrees" );
  }
});

假如你僅僅想要使用$.ajax這個功能,不想使用選擇器等功能怎么辦呢?答案很簡單:像你需要使用全部功能一樣,在頁面引用僅有97k的jQuery,然后使用$.ajax。

從這個例子中我們可以看出,耦合對於一個庫的重要性:耦合讓你那些不太被人接受的功能,跟着受歡迎的功能一起被強制使用,這樣,用戶就會逐漸被強奸,逐漸變得認為理所當然,這正是jQuery能夠成為"事實標准"的奧秘。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM