接上篇。
使用函数作为参数创建jQuery对象
当DOM加载完成后要执行的函数,这个分要分三个部分来讲。
第一部分:初始化队列;
jQuery.ready.promise();
jQuery.ready.promise = function( obj ) {
if ( !readyList ) {
//初始化三个队列。
readyList = jQuery.Deferred();
}
return readyList.promise( obj );
}
第二部分:把函数放进队列;
$(function(){ ... })
jQuery.fn.init = function( selector, context, root ) {
rootjQuery = jQuery( document );
root = root || rootjQuery;
if ( jQuery.isFunction( selector ) ) {
return typeof root.ready !== "undefined" ? root.ready( selector ) : selector( jQuery );
}
}
jQuery.fn.ready = function( fn ) {
jQuery.ready.promise().done( fn );
return this;
};
第三部分:执行队列中的函数。
jQuery.ready是怎么执行的,序中有介绍所以不再重复。
jQuery.extend({
ready: function( wait ) {
readyList.resolveWith( document, [ jQuery ] );
}
});
有兴趣的可以看下:没兴趣的可以跳过。
在此之前不得不得介绍两个东西:
1. jQuery.callbacks: 一个多用途的回调列表对象,提供了强大的的方式来管理回调函数列表。(为了便于说明,“函数列表”内的函数都称为方法)
2. jQuery.Deferred: 延迟对象。
jQuery.callbacks
核心是一个list(函数列表)和一个queue(参数队列)。
接受参数:
- once: 确保这个回调列表只执行一次(像一个递延 Deferred)。
- memory: 保持以前的值和将添加到这个列表的后面的最新的值立即执行调用任何回调 (像一个递延 Deferred)。
- unique: 确保一次只能添加一个回调(所以有没有在列表中的重复)。
- stopOnFalse: 当一个回调返回false 时中断调用。
初始化
/**
* options 使用参数创建一个参数私有的对象。
**/
jQuery.Callbacks = function( options ) {
options = typeof options === "string" ? createOptions( options ) : jQuery.extend({}, options);
...
申明并定义属性及其方法
fire = function() {
//参数once
locked = options.once;
fired = firing = true;
for ( ; queue.length; firingIndex = -1 ) {
memory = queue.shift();
while ( ++firingIndex < list.length ) {
//参数stopOnFalse
if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
options.stopOnFalse ) {
firingIndex = list.length;
memory = false;
}
}
}
//参数memory
if ( !options.memory ) {
memory = false;
}
firing = false;
/**
* 设置了参数为once的时候,
* 未设置参数 memory或设置了参数 stopOnFalse 缓冲被销毁,
* 设置参数 memory 且未设置参数 stopOnFalse 缓冲被重置。
**/
if ( locked ) {
if ( memory ) {
list = [];
} else {
list = "";
}
}
},
self = {
add: function() {
if ( list ) {
if ( memory && !firing ) {
firingIndex = list.length - 1;
queue.push( memory );
}
/**
* 把函数或者方法压入list
* 如果是数组则递归
**/
( function add( args ) {
jQuery.each( args, function( _, arg ) {
if ( jQuery.isFunction( arg ) ) {
if ( !options.unique || !self.has( arg ) ) {
list.push( arg );
}
} else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {
add( arg );
}
} );
} )( arguments );
/**
* memory && !firing 会自动刷新缓冲。分析后得:“memory:unique最后一个值,!firing:并未刷新缓冲。”
**/
if ( memory && !firing ) {
fire();
}
}
return this;
},
}
return self;
}
api接口:
add: 把方法压入list;
remove: 把方法从list中方法;
has: 检查方法是否存在于list中;
empty: list = [];
disable: 销毁list和queue;
disabled: 返回通过“return !list;”返回对象是否被销毁;
lock:阻止手动调用“fireWith”刷新,以下几种情况会自动调用disable方法;
1. 刷新缓冲之前,调用lock,
2. 添加了参数”stopOnFalse”,刷新缓冲之后调用lock。
3. 未添加参数”memory”,刷新缓冲之后调用lock。
(描述的并不是很到位,有兴趣的仔细看下代码。)
locked: 检测是否使用了“once”参数或者“lock”方法;
fireWith:把参数压入queue,并执行list中的每一个方法,这个过程我称为刷新一次缓冲;
fire:内部如此调用了“self.fireWith( this, arguments )”;
fired: 检测是“fireWith”方法是否在运行中。
运营过程:
jQuery.Callbacks(): 随意添加方法,随意刷新缓冲。
jQuery.Callbacks(“once”): 随意添加方法,只能刷新一次缓冲,而后list被销毁。
jQuery.Callbacks(“memory”): 随意添加方法,随意刷新缓冲。但每添加一次方法,会刷新一次缓冲。
jQuery.Callbacks(“once memory”): 随意添加方法,只能手动刷新一次,然后每添加一次方法,自动刷新一次缓冲,list=[]。
jQuery.Callbacks(“once stopOnFalse”):随意添加方法,在刷新一次缓冲时,遇到方法返回false,则销毁list。
jQuery.Callbacks(“memory stopOnFalse”):等同于jQuery.Callbacks(“stopOnFalse”) 。 随意添加方法,随意刷新缓冲。然后每添加一次方法,需要手动刷新缓冲。
jQuery.Deferred
jQuery.extend( {
Deferred: function( func ) {
var tuples = [
//创建3个callbacks队列
[ "resolve", "done", jQuery.Callbacks( "once memory" ), "resolved" ],
[ "reject", "fail", jQuery.Callbacks( "once memory" ), "rejected" ],
[ "notify", "progress", jQuery.Callbacks( "memory" ) ]
],
state = "pending",
promise = {
state: function() {
return state;
},
promise: function( obj ) {
return obj != null ? jQuery.extend( obj, promise ) : promise;
}
},
deferred = {};
jQuery.each( tuples, function( i, tuple ) {
var list = tuple[ 2 ],
stateString = tuple[ 3 ];
//promise 动态添加方法。 promise[ done | fail | progress ] = list.add
promise[ tuple[ 1 ] ] = list.add;
/**
* 为 resolve | reject 添加方法
* 只要 resolve | reject 其中执行过一次,另一个就会被销毁,同时 notify 调用lock方法
**/
if ( stateString ) {
list.add( function() {
// state = [ resolved | rejected ]
state = stateString;
// [ reject_list | resolve_list ].disable; progress_list.lock
}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
}
// 定义 deferred[ resolve | reject | notify ]
deferred[ tuple[ 0 ] ] = function() {
deferred[ tuple[ 0 ] + "With" ]( this === deferred ? promise : this, arguments );
return this;
};
// 定义 deferred[ resolveWith | rejectWith | notifyWith ]
deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
} );
// 把合并promise 对象到 deferred
promise.promise( deferred );
if ( func ) {
func.call( deferred, deferred );
}
return deferred;
}
} );
jQuery.Deferred内部创建了一个“deferred”对象。
1. deferred维护了三个列表:resolve, reject,notify。resolve和reject是互斥的,执行了一次,其他的就不能执行了。
2. 为deferred动态添加了“ done | fail | progress, resolve | reject | notify, resolveWith | rejectWith | notifyWith ”方法,分别维护这三个队列。