关于 bulk 暂时没找到例子,所以这篇文章不算完成……
access() 是个很巧妙的方法,它被放置于 core.js 中,作为静态方法存在。
jQuery 是以 DOM 节点为核心,当你使用 $ 获取到对应的 DOM 节点集合后,一切的操作基本上都会围绕这些节点展开。
我粗略的将 jQuery 针对 DOM 节点的操作方法分为两种,一种是 get,获取节点信息,一种是 set,设置节点信息。
对于 get,通常只需要获取节点集合中的第一个元素,例如你要获取元素的高度、宽度、颜色等等,你通常只会得到一个值。
而对于 set,则会对整个集合中的节点生效,例如:
$('div').height(100);
这便将所有 div 的高度设置为 100 像素。
既然一切围绕着节点的集合来操作,那么循环集合便是不可避免的,但如果在每个方法里面都写个 for 循环,是在是有些难堪。这些循环的内容从形式上基本相同,放到每个方法里面纯属冗余,还不如单独提取出来,在一个新的方法里面对集合做操作。这就是 access() 方法的作用。
先来看看 access() 的参数列表:
access: function( elems, fn, key, value, chainable, emptyGet, raw )
elems 就是要循环的节点集合。
fn 是需要对节点进行操作的函数。
key 是属性名,例如 $('#test').height(); 这里的 height(字符串)。
value 是值,例如 $('#test').height(100); 中的 100。
chainable 表示是否链式执行,对于 get 类方法,我们会获得一个返回值,例如字符串、数字等等,这时候是不需要链式执行的,而对于 set 类方法,通常需要如此,例如:
$('#test').height(100).width(100).css('color', 'red');
emptyGet 用于节点集合中没有元素时返回的默认值。
raw 为 true,表明 value 是个函数,你经常会在 jQuery 的 API 中看到参数可以为函数,举个我都快举烂的例子,height() 方法,点击http://api.jquery.com/height/ 查看 height() 的文档,你会看到,
.height( function(index, height) )
raw 就是用于区分这种参数的。
开始看源码:
var i = 0,
length = elems.length,
bulk = key == null;
此处的 bulk 指的是批量操作,key 为 null,就是说当前的操作即……
if ( jQuery.type( key ) === "object" ) {
chainable = true;
for ( i in key ) {
jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
}
}
key 为对象,就表明这是一个类似于 { height: 100, width: 200 } 的键值对,是将多步操作合并在了一起,而且这样的操作不能是 get 类方法,因为你没法确定最终的返回值是什么,所以 chainable 设置为 true,并且循环 key 对象来分别调用 access 方法。
} else if ( value !== undefined ) {
chainable = true;
if ( !jQuery.isFunction( value ) ) {
raw = true;
}
value 存在,表明是 set 类方法,所以依然是允许链式调用。raw 的含义上面介绍过了。
if ( bulk ) {
// 批量操作针对整个集合来运行
if ( raw ) {
fn.call( elems, value );
fn = null;
// 除非 value 是个函数
} else {
bulk = fn;
fn = function( elem, key, value ) {
return bulk.call( jQuery( elem ), value );
};
}
}
if ( fn ) {
for ( ; i < length; i++ ) {
fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
}
}
如果我能找到 bulk 的真实例子,那么对上面代码可能就会更好的理解了……
好的,终于到了函数结尾处。注意前面处理的都是 set 类方法,包括设置一个值或设置多个值,那么 get 类方法呢?嘿嘿,它们都可怜巴巴的即在 return 里了。
return chainable ?
elems :
bulk ?`
fn.call( elems ) :
length ? fn( elems[0], key ) : emptyGet;
通过前面的源码能看到,chainable 被设置成了 true,链式调用返回的就是元素集合本身。
如果不是链式调用,那么可认为是 get 类方法。
bulk 为 true,说明需要在所有 elems 上调用 fn,它的操作结果就是返回值。
接下来判断 length,即元素集合中元素的个数,如果集合为空,则返回默认值 emptyGet,否则返回集合中第一个元素与 key 传入 fn。