jQuery源码笔记1

时间:2022-12-02 20:37:35

刚开始对于一个问题比较纠结,那就是$("#div")和document.getElement('div')的区别

刚开始接触jQuery时,认为Jquery库是对DOM操作时,将js的方法进行的封装(其中包括对其进行性能调优,兼容性等)

为了能完全了解它们的区别,我们从jQuery的源码入手。看看其中的究竟。

jQuery.fn = jQuery.prototype = {
constructor: jQuery,
init: function( selector, context, rootjQuery ) {
var match, elem, ret, doc;
// Handle $(""), $(null), $(undefined), $(false)
//从英语注释中,我们可以看出selector是一个类似于#id的这样的字符
if ( !selector ) {
return this;//return的使用,一般是退出函数
}
// Handle $(DOMElement)
if ( selector.nodeType ) {
this.context = this[0] = selector;
this.length = 1;
return this;
}
// Handle HTML strings
/*
这里我曾尝试alert(selector),首先我是先在IE和谷歌下测试,发现,连续出现3次alert.然后,我再次尝试typeof selector发现,前两次,显示function,而最后一次是显示string
推测:这里的init函数可能被调用了3次,并且selector再最后一次时,进过了处理
*/
if ( typeof selector === "string" ) {
if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
// Assume that strings that start and end with <> are HTML and skip the regex check
match = [ null, selector, null ];

} else {
/*
我们仔细分析这个正则rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,
复习一下\w是匹配大小写a-z和数字(0-9),所以这个应该比较容易理解
之前我尝试举了一个例子如 $("#div1");这里的match里面显示是#div1,,div1
match[0]是匹配的原数据
*/
match = rquickExpr.exec( selector );
}
// Match html or make sure no context is specified for #id
if ( match && (match[1] || !context) ) {
// HANDLE: $(html) -> $(array)
if ( match[1] ) {
context = context instanceof jQuery ? context[0] : context;
doc = ( context && context.nodeType ? context.ownerDocument || context : document );

// scripts is true for back-compat
selector = jQuery.parseHTML( match[1], doc, true );
if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
this.attr.call( selector, context, true );
}

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 );
},


上面是jQuery.fn的函数,是jQuery库中一个非常重要的函数,我们看到它其中的init属性。定义了Jquery的选择器的信息。

看下面的代码:


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

// scripts is true for back-compat
selector = jQuery.parseHTML( match[1], doc, true );
if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
this.attr.call( selector, context, true );
}

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;
}


match数组中存放着根据正则筛选出来的结果。其中match[0]存放着原数据,如果match[1]为空了,那match[2]存放着选择器的名称。代码使用了一句

elem = document.getElementById( match[2] )

跟js中一样,取到了想要的dom节点。

this.length = 1;
this[0] = elem;
看来jQuery将elem的属性存放在对象的0属性中。

那我们试一下如下代码:

alert($("#div1")[0].nodeName);//DIV 找到的elem,这个js方法定义的dom节点