jQuery serialize模块是对象数组序列化模块。
首先我们先看一下《JavaScript高级程序设计》中的序列化函数,专门用于form参数序列化的。
serialize函数
function
serialize(form){
var
parts =
[],
field
=
null
,
i,
len,
j,
optLen,
option,
optValue;
for
(i = 0, len = form.elements.length; i < len; i++
){
field
=
form.elements[i];
switch
(field.type){
case
"select-one"
:
case
"select-multiple"
:
if
(field.name.length){
for
(j = 0, optLen = field.options.length; j < optLen; j++
){
option
=
field.options[j];
if
(option.selected){
optValue
= ""
;
if
(option.hasAttribute){
optValue
= (option.hasAttribute("value")) ?
option.value : ooption.text);
}
else
{
optValue
= (option.attributes["value"].specified ?
option.value : option.text);
}
parts.push(encodeURIComponent(field.name)
+ "=" +
encodeURIComponent(optValue));
}
}
}
case
undefined:
case
"file"
:
case
"submit"
:
case
"reset"
:
case
"button"
:
break
;
case
"radio"
:
case
"checkbox"
:
if
(!
fied.checked){
break
;
}
default
:
if
(field.name.length){
parts.push(encodeURIComponent(field.name)
+ "=" +
encodeURIComponent(field.value));
}
}
}
return
parts.join("&"
);
}
}
这能帮我们理解下面有些操作,当然从整体实现是差不多的。
但是jQuery提供了利用递归将深入对象或数组内部去序列化,而该方法只能对其下一级序列化,不能再深入下去。
而且jQuery能对满足要求对象、数组进行序列化。
jQuery.param
jQuery.param =
function
( a, traditional ) {
var
prefix,
s
=
[],
//
内部函数充填函数
add =
function
( key, value ) {
//
如果value是一个函数,运行并得到其值
value = jQuery.isFunction( value ) ? value() : ( value ==
null
? ""
: value );
//
向数组s中推入字符串"key=value"
s[ s.length ] = encodeURIComponent( key ) + "=" +
encodeURIComponent( value );
};
//
如果traditional为true,提供jQuery1.3.2以下版本兼容处理
//
如果traditional没定义
if
( traditional ===
undefined ) {
//
将traditional设置成jQuery.ajaxSettings.traditional
traditional = jQuery.ajaxSettings &&
jQuery.ajaxSettings.traditional;
}
//
如果a数组,假设其是一个包含元素的数组
if
( jQuery.isArray( a ) || ( a.jquery && !
jQuery.isPlainObject( a ) ) ) {
//
Serialize the form elements
//
对a中所有元素的name和value推入s数组
jQuery.each( a,
function
() {
add(
this
.name,
this
.value );
});
//
否则
}
else
{
//
如果是traditional方式,则以老的方式encode(jQuery1.3.2以下版本)
//
否则递归encode
for
( prefix
in
a ) {
buildParams( prefix, a[ prefix ], traditional, add );
}
}
//
将s数组用&连接成字符串,将空白替换成+
return
s.join( "&" ).replace( r20, "+"
);
};
jQuery.param能将所有参数序列化,提供了对jQuery1.3.2一下版本不深入对象内部的兼容模式。
buildParams函数
function
buildParams( prefix, obj, traditional, add ) {
var
name;
//
如果obj是一个数组
if
( jQuery.isArray( obj ) ) {
//
序列化数组所有元素
jQuery.each( obj,
function
( i, v ) {
//
如果tranditional为true,或者prefix即当前obj名字为xxx[]
if
( traditional ||
rbracket.test( prefix ) ) {
//
则v可当成常量直接推入
add( prefix, v );
//
否则,即prefix不是xxx[]形式,可能会xxx或者xxx[i]形式
}
else
{
//
v不是常量(是数组或者对象),如果v此时不是数组或则对象,则下次可以当成是常量了,即变成xxx[]
//
否则变成xxx[i],递归
buildParams( prefix + "[" + (
typeof
v === "object" ? i : "" ) + "]"
, v, traditional, add );
}
});
//
否则,非tranditional且obj是对象
}
else
if
( !traditional && jQuery.type( obj ) === "object"
) {
//
遍历序列化
for
( name
in
obj ) {
//
递归,变成xxx[name]
buildParams( prefix + "[" + name + "]"
, obj[ name ], traditional, add );
}
}
else
{
//
到这里,证明不是对象也不是数组,或者是traditional模式,那么直接添加吧
add( prefix, obj );
}
};
如果是传统模式,则不递归,直接输出,否则递归。
jQuery.fn.serialize
jQuery.fn.serialize =
function
() {
//
利用jQuery.param和jQuery.fn.serializeArray
return
jQuery.param(
this
.serializeArray() );
};
序列化函数,实际上是调用param来序列化。
不过先要用serializeArray组装一下。
jQuery.fn.serializeArray
jQuery.fn.serializeArray:
function
() {
//
使用jQuery.fn.map遍历所有元素
return
this
.map(
function
(){
//
读取this.elements
var
elements = jQuery.prop(
this
, "elements"
);
//
如果elements存在则变成数组返回,否则返回this
return
elements ? jQuery.makeArray( elements ) :
this
;
})
//
过滤
.filter(
function
(){
//
得到type
var
type =
this
.type;
//
Use .is(":disabled") so that fieldset[disabled] works
//
如果该元素有name属性,并且这个元素不是:disabled
return
this
.name && !jQuery(
this
).is( ":disabled" ) &&
//
如果节点名字是input、select、textarea或者keygen,
//
并且type不是submit、button、image或reset这些可提交元素
rsubmittable.test(
this
.nodeName ) && !rsubmitterTypes.test( type ) &&
//
如果this.checked为true,或者不是checkbox、radio
(
this
.checked || !
manipulation_rcheckableType.test( type ) );
//
满足的保留,否则过滤
})
//
再次map遍历所有剩下元素
.map(
function
( i, elem ){
//
通过.val获取elem的值
var
val = jQuery(
this
).val();
//
如果val为null
return
val ==
null
?
//
则返回null
null
:
//
否则如果是数组
jQuery.isArray( val ) ?
//
遍历数组的子元素
jQuery.map( val,
function
( val ){
//
组装成下面形式的元素组成的数组
return
{ name: elem.name, value: val.replace( rCRLF, "\r\n"
) };
}) :
//
返回这种形式
{ name: elem.name, value: val.replace( rCRLF, "\r\n"
) };
}).get();
//
转成数组返回,此时不能链式了
};
组装参数对象,并过滤掉一些不需要序列化的元素。
jQuery.fn.map
jQuery.fn.map =
function
( callback ) {
return
this
.pushStack( jQuery.map(
this
,
function
( elem, i ) {
return
callback.call( elem, i, elem );
}));
};
我们可以看出其主要使用了jQuery.map来实现的。
jQuery.map
jQuery.map =
function
( elems, callback, arg ) {
var
value,
i
= 0
,
length
=
elems.length,
isArray
=
isArraylike( elems ),
ret
=
[];
//
先看看elems是不是数组
if
( isArray ) {
//
遍历数组
for
( ; i < length; i++
) {
//
得到callback的返回值
value =
callback( elems[ i ], i, arg );
//
组装返回值数组
if
( value !=
null
) {
ret[ ret.length ]
=
value;
}
}
//
如果不是数组,那么就当他是一个对象
}
else
{
//
遍历其所有key
for
( i
in
elems ) {
//
得到callback的返回值
value =
callback( elems[ i ], i, arg );
//
组装返回值数组
if
( value !=
null
) {
ret[ ret.length ]
=
value;
}
}
}
//
合并所有嵌套数组
return
core_concat.apply( [], ret );
};

