原创:jquery框架分析第三章: 深入函数jQuery.fn.init
作者 斯人 | 发布于 2012 年 1 月 5 日
(function( window, undefined ) {
var document = window.document,//获取document对象 保存为一个局部变量
	navigator = window.navigator,//获取浏览器的相关信息 保存为一个局部变量
	location = window.location;//获取URL信息
var jQuery = (function() { //定义一个匿名函数 jQuery

// 创建JQUERY对象
var jQuery = function( selector, context ) {
		//注意哦 这里并非直接new jQuery
		return new jQuery.fn.init( selector, context, rootjQuery );
	},
......

先说下这个匿名函数
我们看一下 jQuery.fn.init定义的地方 代码如下

jQuery.fn = jQuery.prototype = {
	constructor: jQuery,
	init: function( selector, context, rootjQuery ) {
		var match, elem, ret, doc;

		// Handle $(""), $(null), or $(undefined)
		if ( !selector ) {
			return this;
		}

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

		// The body element only exists once, optimize finding it
		if ( selector === "body" && !context && document.body ) {
			this.context = document;
			this[0] = document.body;
			this.selector = selector;
			this.length = 1;
			return this;
		}

		// Handle HTML strings
		if ( typeof selector === "string" ) {
			// Are we dealing with HTML string or an ID?
			if ( selector.charAt(0) === 3 ) {
				// Assume that strings that start and end with <> are HTML and skip the regex check
				match = [ null, selector, null ];

			} else {
				match = quickExpr.exec( selector );
			}

			// Verify a match, and that no context was specified for #id
			if ( match && (match[1] || !context) ) {

				// HANDLE: $(html) -> $(array)
				if ( match[1] ) {
					context = context instanceof jQuery ? context[0] : context;
					doc = ( context ? context.ownerDocument || context : document );

					// If a single string is passed in and it's a single tag
					// just do a createElement and skip the rest
					ret = rsingleTag.exec( selector );

					if ( ret ) {
						if ( jQuery.isPlainObject( context ) ) {
							selector = [ document.createElement( ret[1] ) ];
							jQuery.fn.attr.call( selector, context, true );

						} else {
							selector = [ doc.createElement( ret[1] ) ];
						}

					} else {
						ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
						selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
					}

					return jQuery.merge( this, selector );

				// HANDLE: $("#id")
				} else {
					elem = document.getElementById( match[2] );

					// Check parentNode to catch when Blackberry 4.6 returns
					// nodes that are no longer in the document #6963
					if ( elem && elem.parentNode ) {
						// Handle the case where IE and Opera return items
						// by name instead of ID
						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: $(expr, $(...))
			} else if ( !context || context.jquery ) {
				return ( context || rootjQuery ).find( selector );

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

		// HANDLE: $(function)
		// Shortcut for document ready
		} else if ( jQuery.isFunction( selector ) ) {
			return rootjQuery.ready( selector );
		}

		if ( selector.selector !== undefined ) {
			this.selector = selector.selector;
			this.context = selector.context;
		}

		return jQuery.makeArray( selector, this );
	}

下面分析下这个函数
constructor: jQuery //让jQuery.fn的constructor(构造函数)属性指向jQuery自身

init: function( selector, context, rootjQuery )这里就是定义init的地方
我们详细看一下
里面传入了三个参数现在我们还不知道是做什么的.我们继续往下看

                if ( !selector ) {//传过来如果为假
			return this;//返回jQuery对象.注意这里返回的是jQuery域,而不是init的域!
		}

		// nodeType 如果为真 说明 selector已经是一个对象了
                //那么返回
		if ( selector.nodeType ) {
			this.context = this[0] = selector;
			this.length = 1;
			return this;
		}

这里应该看明白了吧
继续

//如果selector是body体?因为页面里只有一个body体.所以 直接获取body对象 返回
if ( selector === "body" && !context && document.body ) {
			this.context = document;
			this[0] = document.body;
			this.selector = selector;
			this.length = 1;
			return this;
		}

现在应该能明白了..selector是一个选择器,也就是 $(“*”)
继续 下面这个比较重要

if ( typeof selector === "string" ) {  //如果是字符串
			//如果 是 $("<*>")这样的结构? 如果你对jquery用的很熟,那么你应该知道 这是创建一个element
			if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
				//放入临时变量里
				match = [ null, selector, null ];

			} else {
                                 //干吗的? 在上面定义的 
                                 //quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
                                //如果你熟悉正则表达式那你应该知道是干吗的 比如你执行 $("#test")那么返回数组
                                //["#test",null,"test"]当然
                                //这只是其中一个
				match = quickExpr.exec( selector );
			}

			// 
			if ( match && (match[1] || !context) ) {
				if ( match[1] ) {
                                       //context是jQuery的属性?  三目运算符 不用说了吧
					context = context instanceof jQuery ? context[0] : context;
                                       //获取文档对象 
                                       //没有就获取document对象
					doc = ( context ? context.ownerDocument || context : document );

					//执行$("<a>") 返回数组 ["<a>",a]
					ret = rsingleTag.exec( selector );

					if ( ret ) {
						if ( jQuery.isPlainObject( context ) ) {
							selector = [ document.createElement( ret[1] ) ];
							jQuery.fn.attr.call( selector, context, true );

						} else {
							selector = [ doc.createElement( ret[1] ) ];
						}

					} else {
						ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
						selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
					}

					return jQuery.merge( this, selector );

				// HANDLE: $("#id")
				} else {
					elem = document.getElementById( match[2] );

					// Check parentNode to catch when Blackberry 4.6 returns
					// nodes that are no longer in the document #6963
					if ( elem && elem.parentNode ) {
						// Handle the case where IE and Opera return items
						// by name instead of ID
						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: $(expr, $(...))
			} else if ( !context || context.jquery ) {
				return ( context || rootjQuery ).find( selector );

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

		// HANDLE: $(function)
		// Shortcut for document ready
		} else if ( jQuery.isFunction( selector ) ) {
			return rootjQuery.ready( selector );
		}

		if ( selector.selector !== undefined ) {
			this.selector = selector.selector;
			this.context = selector.context;
		}

		return jQuery.makeArray( selector, this );

我们模仿一下..看看

(function(window){
    var o=window.$=function(){
        return new o.fn.init();
    };
    o.fn=o.prototype={
        init:function(a){//此处的this作用域指向o.fn
            return this;
        },
        attr:function(){
            alert(1)
        }
    }
//一定不要忘了
    o.fn.init.prototype = o.fn;
})(window);
//执行
$().attr();
原文出处:http://www.imsiren.com/archives/108