今天第一次閱讀jQuery源碼,因為讀到用js對表單的序列化,為的是在ajax操作中將表單中各個域的值傳到服務器。書上用了很長的步驟,判斷每一個表單域的屬性,然後拼接。
大概是這樣:
function serialize(form){
var parts = [],
filed = null,
i,
len,
j,
...
for(i=0,len=form.elements.length;i<len;i++){
field=form.elements[i];
switch(field.type){
case "select-one":
case "select-multiple":
...
}
}
}
忽然想到jQuery應該是把這些封裝的很好,就找來讀了。第一次發現這種語言其實很優美,比Java簡潔。
我開始有點喜歡上這門語言了 :)
一般我們是這樣調用的
$('#dataform').serialize()
找了版本1.8.2的jQuery源碼來讀
function () {
return jQuery.param(this.serializeArray());
}
最外層只調用了兩個方法.jQuery.param()和jQuery對象本身的serializeArray(),從字面上理解就是
1.將表單本身序列化成數組
2.然後從中獲得參數
分解如下:
1.先將表單本身序列化成數組
serializeArray()
function () {
return this.map(function () {
return this.elements ? jQuery.makeArray(this.elements) : this;
}).filter(function () {
return this.name && !this.disabled && (this.checked || rselectTextarea.test(this.nodeName) || rinput.test(this.type));
}).map(function (i, elem) {
var val = jQuery(this).val();
return val == null ? null : jQuery.isArray(val) ? jQuery.map(val, function (val, i) {
return {
name: elem.name,
value: val.replace(rCRLF, "\r\n")
};
}) : {
name: elem.name,
value: val.replace(rCRLF, "\r\n")
};
}).get();
}
jQuery.map(callback)將一個數組"映射"成另一個數組,對其中每個元素調用callback方法。
接著返回表單中所有元素的數組。
必須有name,disabled為false,勾選上或是type包含在rinput之中。
取得過濾後元素的val,若val非null,再判斷val是否是Array,對其中每個元素,返回一個對象,對象的name為元素的name,value為元素的val,並替換其中的制表符。
最後獲取其中的數組。
所以這裡看來,原先用js做的復雜switch判斷都包含在了rselectTextarea.test(this.nodeName) || rinput.test(this.type)中,正則表達式果然強大。
具體就是這兩個
/^(?:select|textarea)/i /^(?:color|date|datetime|datetimelocal|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i
哈哈,提到正則表達式,順便給出剛搜到的幽默圖片。

女:哦不!殺手肯定在假期裡跟蹤著她,但是要找到他們,我們必須要在200MB的郵件裡找出像地址一類的東西!
男:沒希望了!
程序員:眾人閃開!我知道正則表達式。看我Perl大法!(啪啪鍵盤聲)
好,現在我們回來繼續看源碼。
2.從數組中中獲得參數
param()
function (a, traditional) {
var prefix, s = [],
add = function (key, value) {
// If value is a function, invoke it and return its value
value = jQuery.isFunction(value) ? value() : (value == null ? "" : value);
s[s.length] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
};
// Set traditional to true for jQuery <= 1.3.2 behavior.
if (traditional === undefined) {
traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
}
// If an array was passed in, assume that it is an array of form elements.
if (jQuery.isArray(a) || (a.jquery && !jQuery.isPlainObject(a))) {
// Serialize the form elements
jQuery.each(a, function () {
add(this.name, this.value);
});
} else {
// If traditional, encode the "old" way (the way 1.3.2 or older
// did it), otherwise encode params recursively.
for (prefix in a) {
buildParams(prefix, a[prefix], traditional, add);
}
}
// Return the resulting serialization
return s.join("&").replace(r20, "+");
}
定義數組s來存放字符串
定義add()來拼接key/value,如果value是方法,則調用,否則返回value值。將key和value編碼後放入s
如果a是數組,那麼假定a就是表單元素的集合。對其中所有元素調用add()。最後將s中所有字符串用&拼接。
總結:
按代碼數來看,jquery寫法與原生js的寫法相差不多。但在擴展性上要好。