jQuery 源码分析(1)

jQuery 是一款开源的,最流行的,面向对象的Javascript框架,因为平时经常使用,也就萌生了阅读源码的想法,尝试着去分析一下,如果有问题,还请大家指点。

阅读 jQuery 源码之前,必须要了解 jQuery 的工作机制,在我看来,实际上 jQuery 是一个标准的以面向对象的程序结构,jQuery 本身是一个类,而每一个我们构建的 jQuery 对象则是这个类实例。

因此我从如下两个方法来入手
1、如何构造 jQuery 对象
2、jQuery对象的继承

1、如何构造 jQuery 对象
jQuery 提供了四种封装jQuery对象的方法,分别是

  • DOMElement
  • HTML strings
  • TAG
  • expr, $(…)

这四种方法的调用如下。

elem = document.getElementsByTagName("div");
elem = $(elem);
var elem = $("<p>hello</p>");
var elem = $("div");
var elem = $("body > div");

通过这些方法,就生成一个jQuery对象。

那么,在jQuery内部,是如何去封装这个对象的呢?
看代码

var jQuery = function( selector, context ) {
                // 创建一个自定义对象,并返回
		return new jQuery.fn.init( selector, context );
	}

不难理解,jQuery 对象实际上通过new运算符创建的一个继承jQuery.prototype.init()返回的对象的原型的对象。

让我们简化jQuery.fn.init方法,并看看他是如何去运作的

jQuery.fn = jQuery.prototype = {
	init: function( selector, context ) {
		var match, elem, ret, doc;
 
		// 如果选择器为空、null、undefined的时候,返回 jQuery对象
		if ( !selector ) {
			return this;
		}
 
		// Handle $(DOMElement)
		if ( selector.nodeType ) {
			// 如果选择器为DOM对象,写入jQuery属性并返回jQuery对象
			this.context = this[0] = selector;
			this.length = 1;
			return this;
		}
 
		// The body element only exists once, optimize finding it
		if ( selector === "body" && !context ) {
			//code here...
			return this;
		}
 
		// Handle HTML strings
		if ( typeof selector === "string" ) {
		// 通过正则判断传入的选择器是HTML字符串还是ID
			// Are we dealing with HTML string or an ID?
			// quickExpr = /^[^< ]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,
 
			match = quickExpr.exec( selector );
 
			// 如果match[1]不为空或者context为空的时候
			if ( match && (match[1] || !context) ) {
 
				// HANDLE: $(html) -> $(array)
				// 如果match[1] 不为空(html字符串)
				if ( match[1] ) {
					// 返回jQuery、选择器两数组合并后的对象
					return jQuery.merge( this, selector );
 
				// HANDLE: $("#id")
				// 如果context为空的时候 (id)
				} else {
					// 尝试按照DOM节点的方式返回jQuery对象
					elem = document.getElementById( match[2] );
 
					if ( elem ) {
						// 如果得到elem对象,但id非match[2]
						if ( elem.id !== match[2] ) {
							return rootjQuery.find( selector );
						}
 
						// Otherwise, we inject the element directly into the jQuery object
						this.length = 1;
						this[0] = elem;
					}
 
					this.context = document;
					this.selector = selector;
					return this;
				}
 
 
			// HANDLE: $("TAG")
			// 如果context为空并且是一个纯字母的字符串
			} else if ( !context && /^\w+$/.test( selector ) ) {
				// 返回jQuery、选择器两数组合并后的对象
				return jQuery.merge( this, selector );
 
			// HANDLE: $(expr, $(...))
			// 如果context为空 或者 context是一个jQuery对象
			} else if ( !context || context.jquery ) {
				// 在上下文或者document对象中找到节点并返回jQuery对象
				return (context || rootjQuery).find( selector );
 
			// HANDLE: $(expr, context)
			// (which is just equivalent to: $(context).find(expr)
			} else {
				return jQuery( context ).find( selector );
			}
 
		// HANDLE: $(function)
		// Shortcut for document ready
		// 对$(document).ready(functon(){});的一个缩写$(function(){});
		} else if ( jQuery.isFunction( selector ) ) {
			return rootjQuery.ready( selector );
		}
 
		// 如果选择器是一个jQuery对象,引用下
		if (selector.selector !== undefined) {
			this.selector = selector.selector;
			this.context = selector.context;
		}
 
		return jQuery.makeArray( selector, this );
 
	}
}

至此,我们就完成了对jQuery对象的构造。

2、jQuery对象的继承
当我们构造完成jQuery对象后,需要jQuery对象继承jQuery中的方法与属性。
看代码

jQuery.fn.init.prototype = jQuery.fn;

如此,就将jQuery的原型赋到jQuery对象的原型上去了,jQuery对象就继承了jQuery初始的方法和属性。

那么,当我需要向已实例化的对象原型中增加方法或者属性怎么办?

这就需要用到扩展方法 –> extend

下次接着说~

原文链接(529 views)|暂无评论(赶紧抢沙发)