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 );
};
参考: