注:
1.本文分析的代码为jQuery.1.11.1版本,在官网上下载未压缩版即可
2.转载请注明出处
$() function,
a clone of the object is created. This new jQuery object references the same DOM elements as the initial one.init = jQuery.fn.init = function( selector, context ) {
var match, elem;
//处理jQuery()形式,返回空的jQuery对象
// HANDLE: $(""), $(null), $(undefined), $(false)
if ( !selector ) {
return this;
}
// Handle HTML strings
/*#源码分析
*匹配html(以<开头,以>结尾,或者是<tag>...形式,推荐写严格的html),或者是#id形式,并且确保,#id情况下,没有context
*/
if ( typeof selector === "string" ) {
if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
/*#源码分析
*假设以<开头,以>结尾的,并且长度大于3的String都是htmlString,然后存到match中
*/
// Assume that strings that start and end with <> are HTML and skip the regex check
match = [ null, selector, null ];
} else {
match = rquickExpr.exec( selector );
}
/*#源码分析
*what is match?
*我们分析过rquickExpr这个正则表达式,它有两个分组(最外面的那个分组不捕获,没算),
*这样使用exec方法后,如果匹配到了,则应该返回一个长度为3,包括index和input属性的数组。
*那么match[0]是整体匹配的数组,match[1]是匹配的<tag>标签(如果有),match[2]匹配#id(如果有)
*显然match[1],match[2]只能有一个被捕获
*/
// Match html or make sure no context is specified for #id
if ( match && (match[1] || !context) ) {
//处理jQuery( html [, ownerDocument ] ),根据html生成dom元素,返回jQuery对象,就像下面的注释$(html) -> $(array)
//match[1]
// HANDLE: $(html) -> $(array)
if ( match[1] ) {
/*#源码分析
*如果context是jQuery对象,转为js原生对象.
*我们说过,jQuery对象就是给js原生对象包装了了一些方法的对象,而原生对象以类数组的形式存在jQuery中,
*所以context[0],就是去jQuery对象中的第一个原生对象,在这里context期待传入的就是document或者$(document)
*/
context = context instanceof jQuery ? context[0] : context;
/*#源码分析
*这里调用了jQuery.parseHTML方法,就是把htmlString转为dom数组
*还调用了jQuery.merge(first,second),接收两个"类数组"参数,
*这个方法是把第二个数组追加到第一个数组尾部,会改变第一个数组
*前面讲过,jQuery对象具有类数组结构,当前还没有操作this,它的length = 0
*所以下面这段代码,就是把htmlString转为dom数组并追加到this的尾部。
*/
// scripts is true for back-compat
// Intentionally let the error be thrown if parseHTML is not present
jQuery.merge( this, jQuery.parseHTML(
match[1],
context && context.nodeType ? context.ownerDocument || context : document,
true
) );
/*#源码分析
*处理jQuery( html, attributes )这种用法
*第一个参数必须是单标签,第二个参数是一个普通对象,类似{html:"hello world",id:"test"}
*注意,这种情况下,会走上面的分支,已经把单标签转为dom并拼接到了this中了
*/
// HANDLE: $(html, props)
if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
for ( match in context ) {
/*#源码分析
*这里的match是context的属性
*如果有match的方法,就会调用match方法
*比如{html:"hello world",id:"test"},就会调用this.html("hello world")方法
*否则按照属性处理
*/
// Properties of context are called as methods if possible
if ( jQuery.isFunction( this[ match ] ) ) {
this[ match ]( context[ match ] );
// ...and otherwise set as attributes
} else {
this.attr( match, context[ match ] );
}
}
}
return this;
/*#源码分析
*处理match[2]被捕获到的情况,也就是#id的情况
*/
// 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
// 为了兼容Blackberry 4.6中的一个bug,不但判断element,还要判断elem.parentNode
if ( elem && elem.parentNode ) {
// Handle the case where IE and Opera return items
// by name instead of ID
/*#源码分析
*早期的IE的document.getElementById()有bug,在查找元素时,会把表单的元素的name也看成是id,
*这时候使用find方法来兼容,搜索一下"rootjQuery =",会发现rootjQuery = jQuery( document );
*/
if ( elem.id !== match[2] ) {
return rootjQuery.find( selector );
}
/*#源码分析
*否则直接放到this[0]中
*/
// Otherwise, we inject the element directly into the jQuery object
this.length = 1;
this[0] = elem;
}
this.context = document;
this.selector = selector;
return this;
}
/*#源码分析
*处理$(复杂选择器的情况),采用find方法处理并返回,
*这里两个else的判断,就是为了确保是jQuery对象调用find方法,
*如果context不是jQuery对象,使用constructor构造一个
*context.jquery-->jquery是jQuery.fn上的一个版本属性,在此用这个来判断是否是jQuery对象。
*/
// 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 );
}
/*#源码分析
*else selector不是String类型的
*/
// HANDLE: $(DOMElement)
} else if ( selector.nodeType ) {
/*#源码分析
*处理$(DOMElement)形式,这个比较简单,就是加到this[0]上
*/
this.context = this[0] = selector;
this.length = 1;
return this;
// HANDLE: $(function)
// Shortcut for document ready
} else if ( jQuery.isFunction( selector ) ) {
/*#源码分析
*$(function)形式,就是调用了$(document).ready()方法
*/
return typeof rootjQuery.ready !== "undefined" ?
rootjQuery.ready( selector ) :
// Execute immediately if ready is not present
selector( jQuery );
}
/*#源码分析
*如果selector.selector !== undefined,那么selector本身可能就是一个jQuery对象,做了如下处理,为什么呢?!不知道
*/
if ( selector.selector !== undefined ) {
this.selector = selector.selector;
this.context = selector.context;
}
/*#源码分析
*jQuery.makeArray(arr)是把类数组,转为纯数组形式,API是这么说的.
*实际上makeArray还有第二个参数,但仅限内部使用,就是现在这种情况
*jQuery.makeArray( arr, results ) -->把调用jQuery.merge把arr数组追加到results尾部
*这里会处理jQuery( elementArray )、jQuery( object )这两种情况
*/
return jQuery.makeArray( selector, this );
};jQuery方法源码解析--jQuery($)方法(一),布布扣,bubuko.com
原文:http://blog.csdn.net/yangyang_cs/article/details/38585507