Core源码

core.js种子模块

  1. 提供静态方法或属性,如$.extend(拷贝对象,首参true深拷贝)、$.each(遍历对象,返回首参对象)、$.map(遍历对象,创建新数组返回)、$.grep(过滤数组)、$.merge(拼接数组,返回首参对象)、$.proxy(改变函数执行的上下文)、$.makeArray(转变为数组)、$.inArray(返回元素在数组中的索引)、$.camelCase(转变为驼峰式书写)、$.nodeName(判断元素的nodeName是否和期望相同)、$.trim(移除字符串首尾空格)、$.globalEval(创建script节点执行代码)、$.type(类型判断)、$.isEmptyObject(是否空对象)、$.isPlainObject(是否普通对象)、$.isNumeric(是否数值或数值型字符串)、$.isWindow(是否window对象)、$.isArray(是否数组)、$.isFunction(是否函数)、$.noop(空函数)、$.error(创建错误对象)、$.now(当前时间)、$.support(浏览器能力检测)、$.guid(jquery内方法的guid,便于移除函数)、$.isReady(jquery加载完成)、$.expando(单次加载jquery的标识符)。
  2. 通过new jQuery.fn.init(selector,context)形式创建jquery对象,该jquery对象继承了$.fn中原型发放或属性,参见init.js。
  3. 为jquery对象提供原型方法或属性,如$.fn.toArray(将dom对象转化为数组)、$.fn.get(获取dom对象)、$.fn.pushStack(以堆栈形式保存本次获取的jquery对象,prevObject保存前次jquery对象)、$.fn.each(遍历dom对象)、$.fn.map(遍历dom对象)、$.fn.slice(获取dom对象的部分)、$.fn.first(获取首个jquery对象)、$.fn.last(获取末一个jquery对象)、$.fn.eq(获取index序号的jquery对象)、$.fn.end(以prevObject获取前一个jquery对象)、$.fn.push(数组push方法处理dom对象)、$.fn.sort(数组sort方法处理dom元素)、$.fn.splice(数组splice处理dom元素)、$.fn.constructor(返回$)、$.fn.jquery(返回版本号)、$.fn.length(dom对象的个数)。
define( [
	"./var/arr",// [] 提供数组的一帮方法
	"./var/document",// window.document
	"./var/getProto",// Object.getPrototypeOf
	"./var/slice",// arr.slice
	"./var/concat",// arr.concat
	"./var/push",// arr.push
	"./var/indexOf",// arr.indexOf
	"./var/class2type",// {} 以键值对类型存储toString方法的简单类型;并提供对象的一般方法
	"./var/toString",// class2type.toString
	"./var/hasOwn",// class2type.hasOwnProperty
	"./var/fnToString",// hasOwn.toString
	"./var/ObjectFunctionString",// fnToString.call( Object );
	"./var/support",// {} 存储浏览器能力检测相关内容
	"./core/DOMEval"// function(code,dom) 创建script节点插入dom,执行code后,删除该script节点
], function( arr, document, getProto, slice, concat, push, indexOf,
	class2type, toString, hasOwn, fnToString, ObjectFunctionString,
	support, DOMEval ) {

var
	version = "@VERSION",

	// 构建jquery对象
	jQuery = function( selector, context ) {
		return new jQuery.fn.init( selector, context );
	},

	// 去除s收尾两端的空格
	rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,

	// 驼峰式转换需要
	rmsPrefix=/^-ms-/,
	rdashAlpha=/-([a-z])/g,
	fcamelCase=function(all,letter){
		return letter.toUpperCase();
	};

// 公有方法
jQuery.fn = jQuery.prototype = {
	jquery: version,// 版本
	constructor: jQuery,// jquery对象的构造函数
	length: 0,// jquery对象的默认值

	// slice方法转化为数组
	toArray: function() {
		return slice.call( this );
	},

	// 获取Dom元素,负值反向获取,null数组输出
	get: function( num ) {
		return num != null ?
			( num < 0 ? this[ num + this.length ] : this[ num ] ) :
			slice.call( this );
	},

	// 创建jquery对象堆栈,压入ret中,ret.prevObject属性存储当前的dom元素
	// $("#btns").eq(1),eq方法中执行pushStack,ret变为[$,$("#btns")[1]],prevObject存储$("#btns")
	pushStack: function( elems ) {
		var ret = jQuery.merge( this.constructor(), elems );// this.constructor()即$,长度为0
		ret.prevObject = this;
		return ret;
	},

	// 遍历dom对象,执行callback回调函数,
        // jquery对象为类数组对象,$(".btns")[i]获取dom对象
	each: function( callback ) {
		return jQuery.each( this, callback );
	},

	// 遍历后选取部分jquery对象
	map: function( callback ) {
		return this.pushStack( jQuery.map( this, function( elem, i ) {
			return callback.call( elem, i, elem );
		} ) );
	},

	// 用slice方法截取jquery对象数组的部分
	slice: function() {
		return this.pushStack( slice.apply( this, arguments ) );
	},

	first: function() {
		return this.eq( 0 );
	},

	last: function() {
		return this.eq( -1 );
	},

	// 获取index=i的jquery对象
	eq: function( i ) {
		var len = this.length,
			j = +i + ( i < 0 ? len : 0 );
		return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
	},

	// 获取前一次jquery对象,或者返回jquery构造函数
	end: function() {
		return this.prevObject || this.constructor();
	},

	push: push,
	sort: arr.sort,
	splice: arr.splice
};

// 首参为布尔值时,是否深拷贝,将拷贝对象options内容复制给目标对象target,同时改变target
// target不存在,且options仅有一项时,将options内容拷贝给全局变量jQuery,用来制作插件等
jQuery.extend = jQuery.fn.extend = function() {
	var options, name, src, copy, copyIsArray, clone,
		target = arguments[ 0 ] || {},
		i = 1,
		length = arguments.length,
		deep = false;

	if ( typeof target === "boolean" ) {
		deep = target;

		target = arguments[ i ] || {};
		i++;
	}

	// 非数组或非函数,目标对象target赋值为空对象
	if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
		target = {};
	}

	// 没有target,仅有一项options时,target赋值为jQuery全局变量,添加插件方法
	if ( i === length ) {
		target = this;
		i--;
	}

	for ( ; i < length; i++ ) {
		if ( ( options = arguments[ i ] ) != null ) {

			for ( name in options ) {
				src = target[ name ];
				copy = options[ name ];

				if ( target === copy ) {// 基本类型===成立
					continue;
				}

				if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
					( copyIsArray = jQuery.isArray( copy ) ) ) ) {

					if ( copyIsArray ) {
						copyIsArray = false;
						clone = src && jQuery.isArray( src ) ? src : [];
					} else {
						clone = src && jQuery.isPlainObject( src ) ? src : {};
					}

					target[ name ] = jQuery.extend( deep, clone, copy );
				} else if ( copy !== undefined ) {
					target[ name ] = copy;
				}
			}
		}
	}

	return target;
};

// 静态方法,jquery对象未继承
jQuery.extend( {

	// 全局jquery的统一标识符,一次加载生成一个
	expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),

	// jquery加载完成
	isReady: true,

	// 创建错误对象
	error: function( msg ) {
		throw new Error( msg );
	},

	// 空函数
	noop: function() {},

	// 是否函数
	isFunction: function( obj ) {
		return jQuery.type( obj ) === "function";
	},

	// 是否数组
	isArray: Array.isArray,

	// 是否window对象
	isWindow: function( obj ) {
		return obj != null && obj === obj.window;
	},

	// 是否数值或数值化字符串
	isNumeric: function( obj ) {
		var type = jQuery.type( obj );
		return ( type === "number" || type === "string" ) &&

			// parseFloat函数传参为NaN时,输出仍为NaN,其余数值化字符串转化为数值
			!isNaN( obj - parseFloat( obj ) );
	},

	// 是否普通对象
	isPlainObject: function( obj ) {
		var proto, Ctor;

		if ( !obj || toString.call( obj ) !== "[object Object]" ) {
			return false;
		}

		proto = getProto( obj );// Object.getPrototypeOf获取原型obj.prototype

		if ( !proto ) {
			return true;
		}

		// {}.hasOwnProperty获取对象的自有属性
		Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
		return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
	},

	// 是否空对象
	isEmptyObject: function( obj ) {
		var name;
		for ( name in obj ) {
			return false;
		}
		return true;
	},

	// 判断类型
	type: function( obj ) {
		if ( obj == null ) {
			return obj + "";
		}

		return typeof obj === "object" || typeof obj === "function" ?
			class2type[ toString.call( obj ) ] || "object" :
			typeof obj;
	},

	// 插入script节点的方式执行一段code代码,code代码所用变量均为全局变量
	globalEval: function( code ) {
		DOMEval( code );
	},

	// "-"连接的字符串转换为驼峰式书写法,且"-ms-"开头的字符串转换为"ms-"开头
	camelCase: function(string){
		return string.replace(rmsPrefix,"ms-").replace(rdashAlpha,fcamelCase);
	},

	// 判断节点elem的nodeName与期望值name是否匹配
	nodeName: function( elem, name ) {
		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
	},

	// 遍历对象或数组,执行callback(value,key)回调函数,callback返回否则遍历终止,上下文为value
	// obj原路返回,除非callback中改变,否则不改变obj值
	each: function( obj, callback ) {
		var length, i = 0;

		if ( isArrayLike( obj ) ) {
			length = obj.length;
			for ( ; i < length; i++ ) {
				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
					break;
				}
			}
		} else {
			for ( i in obj ) {
				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
					break;
				}
			}
		}

		return obj;
	},

	// 去掉字符串收尾两端的空格
	trim: function( text ) {
		return text == null ? "" : ( text + "" ).replace( rtrim, "" );
	},

	// 将arr转化为数组,拼接results后面,返回新的数组
	makeArray: function( arr, results ) {
		var ret = results || [];

		if ( arr != null ) {
			if ( isArrayLike( Object( arr ) ) ) {
				jQuery.merge( ret, typeof arr === "string" ? [ arr ] : arr );
			} else {
				push.call( ret, arr );
			}
		}

		return ret;
	},

	// 从i位置开始查询elem在arr数组中的位置
	inArray: function( elem, arr, i ) {
		return arr == null ? -1 : indexOf.call( arr, elem, i );
	},

	// 将第二个数组拼接到第一个数组后面,同时第一个数组被改变
	merge: function( first, second ) {
		var len = +second.length,
			j = 0,
			i = first.length;

		for ( ; j < len; j++ ) {
			first[ i++ ] = second[ j ];
		}

		first.length = i;

		return first;
	},

	// 遍历执行callback回调过滤数组elems,真值时保留;ivert为否时,执行结果为否值时保留
	grep: function( elems, callback, invert ) {
		var callbackInverse,
			matches = [],
			i = 0,
			length = elems.length,
			callbackExpect = !invert;

		for ( ; i < length; i++ ) {
			callbackInverse = !callback( elems[ i ], i );
			if ( callbackInverse !== callbackExpect ) {
				matches.push( elems[ i ] );
			}
		}

		return matches;
	},

	// 遍历数组或对象执行callback,返回非null时,压入新创建的ret数组中,以ret返回
	map: function( elems, callback, arg ) {
		var length, value,
			i = 0,
			ret = [];

		if ( isArrayLike( elems ) ) {
			length = elems.length;
			for ( ; i < length; i++ ) {
				value = callback( elems[ i ], i, arg );

				if ( value != null ) {
					ret.push( value );
				}
			}
		} else {
			for ( i in elems ) {
				value = callback( elems[ i ], i, arg );

				if ( value != null ) {
					ret.push( value );
				}
			}
		}

		return concat.apply( [], ret );
	},

	// 供绑定事件函数使用的guid,标记函数,以便移除
	guid: 1,

	// 改变fn函数执行的上下文,并输出fn函数,绑定事件中使用可约定函数执行的上下文
	// 解绑时通过guid查找回调函数fn,并从dataPriv中清除,并可向fn传递额外函数
	proxy: function( fn, context ) {
		var tmp, args, proxy;

		// context为字符串,且fn为对象时,以fn作为上下文,fn[context]作为回调函数
		if ( typeof context === "string" ) {
			tmp = fn[ context ];
			context = fn;
			fn = tmp;
		}

		if ( !jQuery.isFunction( fn ) ) {
			return undefined;
		}

		args = slice.call( arguments, 2 );
		proxy = function() {
			return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
		};

		// guid作为函数的标记,记录后,可以通过校验函数guid方式删除函数
		proxy.guid = fn.guid = fn.guid || jQuery.guid++;

		return proxy;
	},

	now: Date.now,// 当前时间
	support: support// 浏览器能力检测
} );

// JSHint would error on this code due to the Symbol not being defined in ES5.
// Defining this global in .jshintrc would create a danger of using the global
// unguarded in another place, it seems safer to just disable JSHint for these
// three lines.
/* jshint ignore: start */
if ( typeof Symbol === "function" ) {
	jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
}

// class2type以键值对类型存储toString方法的简单类型
jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
function( i, name ) {
	class2type[ "[object " + name + "]" ] = name.toLowerCase();
} );

// 判断是否数组或伪数组
function isArrayLike( obj ) {

	var length = !!obj && "length" in obj && obj.length,
		type = jQuery.type( obj );

	if ( type === "function" || jQuery.isWindow( obj ) ) {
		return false;
	}

	return type === "array" || length === 0 ||
		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
}

return jQuery;
} );

 

init.js

  1.  创建jquery对象。
  2. 传参为$(slector,context)形式,在context元素或context对象或当前文档中获取slector,将dom对象包装为jquery对象,添加length、selector、context属性,index序号获取dom对象。
  3. 传参为$(html,ownerDocument)形式,在ownerDocument元素或当前文档中创建html元素,参见parseHTML。
  4. 传参为$(html,props)形式,在当前文档中创建html元素,props为向该html元素添加的属性,或者待执行的jquery方法。
  5. 传参为$(#id)形式,调用getElementById获取dom对象后,封装为jquery对象输出。
  6. 传参为$(tagName),转化为$(slector,context)形式后处理。
  7. 传参为$(callback),文档加载完成后执行callback回调函数,参见ready.js。
define( [
	"../core",// 提供jquery全局变量
	"../var/document",// window.document
	"./var/rsingleTag",// ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ) 匹配html标签名
	"../traversing/findFilter"
], function( jQuery, document, rsingleTag ) {

var rootjQuery,
	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,

	init = jQuery.fn.init = function( selector, context, root ) {
		var match, elem;

		if ( !selector ) {
			return this;
		}

		root = root || rootjQuery;// jQuery( document );

		if ( typeof selector === "string" ) {
			// 字符串以<、>闭合,跳过rquickExpr正则匹配
			if ( selector[ 0 ] === "<" && selector[ selector.length - 1 ] === ">" &&
				selector.length >= 3 ) {

				match = [ null, selector, null ];
			} else {
				match = rquickExpr.exec( selector );
			}

			// 传参字符串匹配rquickExpr中html,或匹配rquickExpr中#id,且没有content
			if ( match && ( match[ 1 ] || !context ) ) {

				// 传参字符串匹配rquickExpr中html
				// context为ownerDocument形式,意味创建DOM元素所在的文档
				// context为props,用于执行jquery对象的方法或为dom元素修改属性、事件
				if ( match[ 1 ] ) {
					context = context instanceof jQuery ? context[ 0 ] : context;

					// jQuery.parseHTML将html字符串转化成dom节点,尾参true时执行字符串中script脚本
					jQuery.merge( this, jQuery.parseHTML(
						match[ 1 ],
						context && context.nodeType ? context.ownerDocument || context : document,
						true
					) );

					// 传参context为创建节点的属性配置props
					if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
						for ( match in context ) {

							// jquery对象拥有match方法时,context[match]作为参数执行该方法
							// 或者修改dom节点的属性
							if ( jQuery.isFunction( this[ match ] ) ) {
								this[ match ]( context[ match ] );
							} else {
								this.attr( match, context[ match ] );
							}
						}
					}

					return this;

				// 处理$(#id)情形,无content
				} else {
					elem = document.getElementById( match[ 2 ] );

					if ( elem ) {

						this[ 0 ] = elem;
						this.length = 1;
					}
					return this;
				}

			// 选择器形式,没有指定context参数,在当前的HTML document中查找DOM元素
			// 有指定context参数,在指定的DOM元素或jquery对象中查找
			} else if ( !context || context.jquery ) {
				return ( context || root ).find( selector );
			} else {
				return this.constructor( context ).find( selector );
			}

		// selector为dom元素,封装为jquery对象后返回
		} else if ( selector.nodeType ) {
			this[ 0 ] = selector;
			this.length = 1;
			return this;

		// 文档载入完成后执行函数,或尚未载入,传参全局变量jquery
		} else if ( jQuery.isFunction( selector ) ) {
			return root.ready !== undefined ? root.ready( selector ) : selector( jQuery );
		}

		return jQuery.makeArray( selector, this );
	};

// new运算符移到init方法中执行的目的,创建jquery实例的时候只需执行$(),不必调用new运算符
// 调用init方法前使用new运算符的必要,不使用时,init方法内部this关键字指向$实例,拥有$.fn的属性和方法
// 		使用时,init方法称为构造器,内部使用this仅和init构造器相关
// 		init.prototype=jQuery.fn使init方法产生的实例,拥有$.fn的原型方法
init.prototype = jQuery.fn;

rootjQuery = jQuery( document );

return init;

} );

 

ready.js 

  1. 文档加载成功时执行函数功能实现,提供$.fn.ready(向文档加载成功时触发的延迟对象添加回调函数;$(callback)调用,简化处理)、$.holdReady(暂停或恢复ready事件)、$.ready.then(用延迟对象的then方法添加成功时触发的回调函数)、$.readyWait(暂停ready事件,该属性归0时执行回调函数)。
define( [
	"../core",
	"../var/document",
	"../deferred"
], function( jQuery, document ) {

var readyList = jQuery.Deferred();// 延迟对象

jQuery.fn.ready = function( fn ) {
	readyList.then( fn );
	return this;
};

jQuery.extend( {
	isReady: false,

	// 调用多次$(fn),各回调函数fn推送到readyList,执行时机为最后一次执行$(fn),适用于异步情况
	readyWait: 1,

	// 暂停或恢复ready事件
	holdReady: function( hold ) {
		if ( hold ) {
			jQuery.readyWait++;
		} else {
			jQuery.ready( true );
		}
	},

	ready: function( wait ) {
		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
			return;
		}

		jQuery.isReady = true;

		if ( wait !== true && --jQuery.readyWait > 0 ) {
			return;
		}

		// 触发执行readyList中回调函数
		readyList.resolveWith( document, [ jQuery ] );
	}
} );

// 向外提供接口添加回调函数
jQuery.ready.then = readyList.then;

function completed() {
	document.removeEventListener( "DOMContentLoaded", completed );
	window.removeEventListener( "load", completed );
	jQuery.ready();
}

// 文档已加载完成,直接执行jQuery.ready;否则绑定文档加载成功的事件执行jQuery.ready
if ( document.readyState === "complete" ||
	( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {

	window.setTimeout( jQuery.ready );
} else {
	document.addEventListener( "DOMContentLoaded", completed );
	window.addEventListener( "load", completed );
}

} );

 

 parseHTML.js 

  1.  将html字符串转化为dom对象形式。尾参keepScripts为真时,执行html字符串中script脚本。
define( [
	"../core",// 提供jquery全局变量
	"../var/document",// window.document
	"./var/rsingleTag",// ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ) 匹配html标签名
	"../manipulation/buildFragment",// 将html字符串转化为dom对象
	"./support"
], function( jQuery, document, rsingleTag, buildFragment, support ) {

// data字符串html,context(可选)指定在哪个document创建元素,keepScripts为true时执行代码
jQuery.parseHTML = function( data, context, keepScripts ) {
	if ( typeof data !== "string" ) {
		return [];
	}
	if ( typeof context === "boolean" ) {
		keepScripts = context;
		context = false;
	}

	var base, parsed, scripts;

	if ( !context ) {
		// support.createHTMLDocument检测浏览器是否支持用document.implementation.createHTMLDocument
		// 		创建另一个document,被iframe包裹
		if ( support.createHTMLDocument ) {
			context = document.implementation.createHTMLDocument( "" );

			base = context.createElement( "base" );
			base.href = document.location.href;
			context.head.appendChild( base );
		} else {
			context = document;
		}
	}

	parsed = rsingleTag.exec( data );// data以<起始只提供创建元素的节点名
	scripts = !keepScripts && [];

	if ( parsed ) {
		return [ context.createElement( parsed[ 1 ] ) ];
	}

	// html字符串中script脚本节点压入scripts中,keepScripts否值移除,不执行脚本,返回创建的dom元素
	parsed = buildFragment( [ data ], context, scripts );

	if ( scripts && scripts.length ) {
		jQuery( scripts ).remove();
	}

	return jQuery.merge( [], parsed.childNodes );
};

return jQuery.parseHTML;

} );
 

附:buildFragment.js

define( [
	"../core",
	"./var/rtagName",// 匹配html节点标签名 ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i )
	"./var/rscriptType",// ( /^$|\/(?:java|ecma)script/i )
	"./wrapMap",// 获取option、tr、tbody包裹节点名称select、table/tbody、table
	"./getAll",// getAll(context,tag) 获取context下所有tagName为tag的节点
	"./setGlobalEval"// "globalEval"属性记录sctipt节点中的语法已执行
], function( jQuery, rtagName, rscriptType, wrapMap, getAll, setGlobalEval ) {

var rhtml = /<|&#?\w+;/;

function buildFragment( elems, context, scripts, selection, ignored ) {
	var elem, tmp, tag, wrap, contains, j,
		fragment = context.createDocumentFragment(),
		nodes = [],
		i = 0,
		l = elems.length;

	for ( ; i < l; i++ ) {
		elem = elems[ i ];

		if ( elem || elem === 0 ) {

			// elem本身为dom对象
			if ( jQuery.type( elem ) === "object" ) {
				jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );


			} else if ( !rhtml.test( elem ) ) {
				nodes.push( context.createTextNode( elem ) );

			// 将html转化成dom对象,插入文档中,用dom方法获取
			} else {
				tmp = tmp || fragment.appendChild( context.createElement( "div" ) );

				// option、tr、tbody元素用select、table/tbody、table包裹
				tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
				wrap = wrapMap[ tag ] || wrapMap._default;
				tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];

				// 用div、select等包裹后,lastChild获取实际添加的元素
				j = wrap[ 0 ];
				while ( j-- ) {
					tmp = tmp.lastChild;
				}

				// html字符串转化为dom对象形式,存储到nodes中
				jQuery.merge( nodes, tmp.childNodes );

				tmp = fragment.firstChild;
				tmp.textContent = "";
			}
		}
	}

	// 清除fragment中元素后,使用遍历方式将nodes中元素推送到fragment中
	fragment.textContent = "";

	i = 0;
	while ( ( elem = nodes[ i++ ] ) ) {

		// 传入的elems本就是dom节点对象的形式
		if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
			if ( ignored ) {
				ignored.push( elem );
			}
			continue;
		}

		contains = jQuery.contains( elem.ownerDocument, elem );

		// fragment中添加elem,tmp获取所有tmp节点
		tmp = getAll( fragment.appendChild( elem ), "script" );

		// 阻止script节点脚本执行
		if ( contains ) {
			setGlobalEval( tmp );
		}

		// script节点压入scripts数组中
		if ( scripts ) {
			j = 0;
			while ( ( elem = tmp[ j++ ] ) ) {
				if ( rscriptType.test( elem.type || "" ) ) {
					scripts.push( elem );
				}
			}
		}
	}

	return fragment;
}

return buildFragment;
} );

 getAll.js

define([
	"../core"
],function(jQuery){

// getAll为单参数时,数组形式返回context;
// 双参数,且tag匹配context的节点类型,获取context下同类子节点(包含context)
// 其余形式,如tag不是节点类型,返回context下tag节点
function getAll(context,tag){

	// 不只文档document上挂载getElementsByTagName、querySelectorAll方法
	// Dom元素上也会挂载getElementsByTagName、querySelectorAll方法
	var ret = typeof context.getElementsByTagName!=="undefined" ?
			context.getElementsByTagName(tag || "*") :
			typeof context.querySelectorAll!=="undefined" ?
				context.querySelectorAll(tag || "*") : [];

	// jQuery.nodeName(elem,'TEXTAREA')判断elem节点的名称是否为'TEXTAREA'
	// jQuery.merge合并两个数组到一个数组上,第一个数组后跟第二个数组的元素
	// tag为空或为context元素的节点名时,获取context和context下同类子节点返回
	// 		否则返回context下tag节点
	return tag===undefined || tag && jQuery.nodeName(context,tag) ?
		jQuery.merge([context],ret) : ret;
}

return getAll;
});

 setGlobalEval.js

define([
	"../data/var/dataPriv"
],function(dataPriv){

// "globalEval"属性记录sctipt节点中的语法已执行
function setGlobalEval(elems,refElements){
	var i=0,
		l=elems.length;

	for ( ; i<l; i++ ){
		dataPriv.set(
			elems[i], "globalEval",
			!refElements || dataPriv.get(refElements[i],"globalEval")
		);
	}
}

return setGlobalEval;
});

 wrapMap.js

define( function() {

var wrapMap = {
	option: [ 1, "<select multiple='multiple'>", "</select>" ],
	thead: [ 1, "<table>", "</table>" ],
	col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
	tr: [ 2, "<table><tbody>", "</tbody></table>" ],
	td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],

	_default: [ 0, "", "" ]
};

wrapMap.optgroup = wrapMap.option;

wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
wrapMap.th = wrapMap.td;

return wrapMap;
} );

 access.js 

  1. 内部模块使用,如css、attr等方法,对elems取值或赋值操作,或取出elem属性单纯执行回调。
define([
	"../core"
],function(jQuery){

// 对elems取值或赋值操作,或取出elem属性单纯执行回调
var access=function(elems,fn,key,value,chainable,emptyGet,raw){
	var i=0,
		len=elems.length,
		bulk=key==null;

	if ( jQuery.type(key)==="object" ){
		chainable=true;
		for ( i in key ){
			access(elems,fn,i,key[i],true,emptyGet,raw);
		}

	}else if( value!==undefined ){
		chainable=true;

		// value不是函数时,raw设置为真值
		if ( !jQuery.isFunction(value) ){
			raw=true;
		}

		// key为null,执行access参数fn,value或作为参数,或通过执行获取参数
		if ( bulk ){
			// key为null,value不是函数,fn以elems、value为参数执行
			if ( raw ){
				fn.call(elems,value);
				fn=null;

			// value为函数时,传参elem及i执行,作为access参数fn的参数,fn首参为$(elem)
			}else{
				bulk=fn;
				fn=function(elem,key,value){
					return bulk.call(jQuery(elem),value);
				};
			}
		}

		// key有值,value有值且非函数时,执行fn(elem,key,value)
		// key有值,value为函数,执行fn(elem,key,value),value作为回调
		// key为null,value为函数,执行fn(elem,null,value.call(elem,i,fn(elem,key)))
		if ( fn ){
			for ( ;i<len;i++ ){
				fn( elems[i], key, raw ? value : value.call(elems[i],i,fn(elems[i],key)) );
			}
		}
	}

	// value不等于undefined时,chainable恒为真;否则根据传参判断
	// value等于undefined时,key为null,fn传参elems取值
	// value等于undefined时,key不等于null,fn传参elems[0]、key取值,或用emptyGet取值
	return chainable ?
		elems :

		// Gets
		bulk ? fn.call(elems) : len ? fn(elems[0],key) : emptyGet;
};

return access;

} );

 

猜你喜欢

转载自schifred.iteye.com/blog/2329759