欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

jQuery源码解读之init函数

程序员文章站 2022-03-06 22:20:24
...

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 

相关标签: jquery