jQuery源码解读之init函数

jQuery的构造方法:

// 直接new了一个对象。同时根据jQuery.fn = jQuery.prototype,jQuery.fn相当于jQuery.prototype。

jQuery = function( selector, context ) {
        return new jQuery.fn.init( selector, context );
},

jQuery.fn.init方法:

init = jQuery.fn.init = function( selector, context, root ) {
    return jQuery.makeArray( selector, this );
};

init.prototype = jQuery.fn;

// init的原型指向了jQuery.fn,而jQuery.fn=jQuery.prototype即init.prototype=jQuery.prototype

// 根据js原型链的知识,我们通过init方法构造出来的对象,能访问jQuery.prototype对象的方法。

// 当我们使用类似$(xxx)的时候,jquery为我们new了一个对象,并且这个对象的原型链指向jQuery.prototype,我们可以直接使用jQuery.prototype上的方法。

源码分析:

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

	// HANDLE: $(""), $(null), $(undefined), $(false)
		//判断selector是否为空,是的话,直接返回this,也就是空的jquery对象。
	if ( !selector ) {
		return this;
	}

	//定义了root为rootjQuery,这里的rootjQuery其实就是jQuery( document ),主要用于选择器为空的时候,用rootjQuery上下文来代替空值,继续下面的链式操作
	root = root || rootjQuery;

	//判断selector是否为字符串、是否为DOM类型、是否是一个function。

	// 如果selector为字符串,通过正则判断selector是不是html字符串

	if ( typeof selector === "string" ) {
		if ( selector[ 0 ] === "<" &&
			selector[ selector.length - 1 ] === ">" &&
			selector.length >= 3 ) {

			//假设以<>开头和结尾的字符串是HTML并跳过正则表达式检查
			match = [ null, selector, null ];

		} else {
			//通过正则判断selector是不是html字符串
			//rquickExpr用来匹配HTML标记和ID表达式
			match = rquickExpr.exec( selector );
		}

		//匹配html或确保没有为#id指定上下文
		//selector为html字符串
		if ( match && ( match[ 1 ] || !context ) ) {

			// HANDLE: $(html) -> $(array)
			//match[1]也就是HTML标记是否存在
			if ( match[ 1 ] ) {
				context = context instanceof jQuery ? context[ 0 ] : context;

				//jquery通过parseHTML(将html字符串转换为dom)和merge(把第二个数组merge到第一个数组)方法
				//将HTML标记转化为由jQuery对象包装的DOM元素,并返回
				jQuery.merge( this, jQuery.parseHTML(
					match[ 1 ],
					context && context.nodeType ? context.ownerDocument || context : document,
					true
				) );

				// HANDLE: $(html, props)
				if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
					for ( match in context ) {

						//如果可能,将上下文的属性称为方法
						if ( jQuery.isFunction( this[ match ] ) ) {
							this[ match ]( context[ match ] );

						// ...并以其他方式设置为属性
						} else {
							this.attr( match, context[ match ] );
						}
					}
				}

				return this;

			// HANDLE: $(#id)
			//不存在html标记时直接通过match[2]也就是ID去取对应元素
			} else {
				elem = document.getElementById( match[ 2 ] );

				if ( elem ) {

					//将元素直接注入jQuery对象
					this[ 0 ] = elem;
					this.length = 1;
				}
				return this;
			}

		// HANDLE: $(expr, $(...))
		//如果不是html字符串,判断有没有context
		//有context的话,使用context调用find方法(也就是sizzle)
		//没有就是用document为context调用find。
		} else if ( !context || context.jquery ) {
			return ( context || root ).find( selector );

		// HANDLE: $(expr, context)
		// (which is just equivalent to: $(context).find(expr)
		} else {
			return this.constructor( context ).find( selector );
		}

	// HANDLE: $(DOMElement)
	} else if ( selector.nodeType ) {
		this[ 0 ] = selector;
		this.length = 1;
		return this;

	// HANDLE: $(function)
	// document ready的缩写
	} else if ( jQuery.isFunction( selector ) ) {
		return root.ready !== undefined ?
			root.ready( selector ) :

			//如果没有准备就立即执行
			selector( jQuery );
	}

	// 处理成jquery数组,这里的makeArray对外是将一个类数组对象转换为真正的数组对象,对内有个重载,就是处理成jquery数组对象。
	return jQuery.makeArray( selector, this );
};

参考:

https://blog.csdn.net/m1213642578/article/details/52490423 

猜你喜欢

转载自blog.csdn.net/qq_30422457/article/details/83413295
今日推荐