搜索
首页web前端js教程jquery构造器的实现代码小结_jquery

显然,能做到这一步,其实现是相当的复杂,这个实现就是它的init方法,jQuery的真实构造器。它功能也随着版本的升级而升级,越来越长。
2009-01-13发布的1.3版

复制代码 代码如下:

init: function( selector, context ) {
// Make sure that a selection was provided
selector = selector || document;
// 处理节点参数,直接添加属性到新实例上
if ( selector.nodeType ) {
this[0] = selector;
this.length = 1;
this.context = selector;
return this;
}
// 处理字符串参数
if ( typeof selector === "string" ) {
// 判定是否为HTML片断还是ID
var match = quickExpr.exec( selector );
if ( match && (match[1] || !context) ) {
// 如果是HTML片断,转换一个由节点构造的数组
if ( match[1] )
selector = jQuery.clean( [ match[1] ], context );
// 如果是ID,则查找此元素,如果找到放进空数组中
else {
var elem = document.getElementById( match[3] );
// Make sure an element was located
if ( elem ){
// 处理 IE and Opera 混淆ID与NAME的bug
if ( elem.id != match[3] )
return jQuery().find( selector );
var ret = jQuery( elem );
ret.context = document;
ret.selector = selector;
return ret;
}
selector = [];
}
} else
//使用Sizzle处理其他CSS表达式,生成实例并返回
return jQuery( context ).find( selector );
// 处理函数参数,直接domReady
} else if ( jQuery.isFunction( selector ) )
return jQuery( document ).ready( selector );
//处理jQuery对象参数,简单地将其两个属性赋给新实例
if ( selector.selector && selector.context ) {
this.selector = selector.selector;
this.context = selector.context;
}
//将上面得到节点数组,用setArray方法把它们变成实例的元素
return this.setArray(jQuery.makeArray(selector));
},

2009-02-19发布的1.32版
复制代码 代码如下:

init: function( selector, context ) {
// Make sure that a selection was provided
selector = selector || document;
// 处理节点参数,直接添加属性到新实例上
if ( selector.nodeType ) {
this[0] = selector;
this.length = 1;
this.context = selector;
return this;
}
//处理字符串参数
if ( typeof selector === "string" ) {
//判定是否为HTML片断还是ID
var match = quickExpr.exec( selector );
if ( match && (match[1] || !context) ) {
// 如果是HTML片断,转换一个由节点构造的数组
if ( match[1] )
selector = jQuery.clean( [ match[1] ], context );
else {
var elem = document.getElementById( match[3] );
// 如果是ID,则查找此元素,如果找到放进空数组中
if ( elem && elem.id != match[3] )
return jQuery().find( selector );
//这里对1.3版做了些优化,更简洁
var ret = jQuery( elem || [] );
ret.context = document;
ret.selector = selector;
return ret;
}
} else
//使用Sizzle处理其他CSS表达式,生成实例并返回
return jQuery( context ).find( selector );
// 处理函数参数,进行domReady操作
} else if ( jQuery.isFunction( selector ) )
return jQuery( document ).ready( selector );
//处理jQuery对象参数,简单地将其两个属性赋给新实例
if ( selector.selector && selector.context ) {
this.selector = selector.selector;
this.context = selector.context;
}
//这里对1.3版做了些扩展,允许传珍上元素集合(HTMLCollection)与节点集合(NodeList),
//元素数组可能是我们用字符串转换过来的,也可以是用户直接传进来的
return this.setArray(jQuery.isArray( selector ) ? selector : jQuery.makeArray(selector));
},

2010-01-13发布的1.4版
复制代码 代码如下:

init: function( selector, context ) {
var match, elem, ret, doc;
//处理空白字符串,null,undefined参数(新增),返回一个非常纯净的实例
if ( !selector ) {
return this;
}
// 处理节点参数,直接添加属性到新实例上
if ( selector.nodeType ) {
this.context = this[0] = selector;//写法上优化
this.length = 1;
return this;
}
//处理字符串参数
if ( typeof selector === "string" ) {
// 判定是否为HTML片断还是ID
match = quickExpr.exec( selector );
if ( match && (match[1] || !context) ) {
//如果是HTML片断
if ( match[1] ) {
//取得文档对象
doc = (context ? context.ownerDocument || context : document);
// 如果是单个标签,直接使用 document.createElement创建此节点并放入数组中
ret = rsingleTag.exec( selector );
if ( ret ) {
//如果后面跟着一个纯净的JS对象,则为此节点添加相应的属性或样式
if ( jQuery.isPlainObject( context ) ) {
selector = [ document.createElement( ret[1] ) ];
jQuery.fn.attr.call( selector, context, true );
} else {
selector = [ doc.createElement( ret[1] ) ];
}
} else {
//改由buildFragment来生成节点集合(NodeList)
ret = buildFragment( [ match[1] ], [ doc ] );
selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
}
} else {
// 如果是ID,则查找此元素,如果找到放进空数组中
elem = document.getElementById( match[2] );
if ( elem ) {
// 处理 IE and Opera 混淆ID与NAME的bug
if ( elem.id !== match[2] ) {
return rootjQuery.find( selector );
}
//这里也做了一些优化,原来是很傻地再生成一个jQuery实例
this.length = 1;
this[0] = elem;
}
this.context = document;
this.selector = selector;
return this;
}
// 如果字符是很简单的标签选择器,那基本没有必要走Sizzle路线,直接getElementsByTagName,很好的优化
} else if ( !context && /^\w+$/.test( selector ) ) {
this.selector = selector;
this.context = document;
selector = document.getElementsByTagName( selector );
// 如果第二个参数不存在或者是jQuery对象,那么用它或rootjQuery调用find查找目标节点(走Sizzle路线)
} else if ( !context || context.jquery ) {
return (context || rootjQuery).find( selector );
// HANDLE: $(expr, context)
// (which is just equivalent to: $(context).find(expr)
} else {
//如果第二个参数已指定为某元素节点,转为jQuery对象,走Sizzle路线
return jQuery( context ).find( selector );
}
// 处理函数参数,直接domReady
} else if ( jQuery.isFunction( selector ) ) {
return rootjQuery.ready( selector );
}
//处理jQuery对象参数,简单地将其两个属性赋给新实例
if (selector.selector !== undefined) {
this.selector = selector.selector;
this.context = selector.context;
}
//这里又做了些许修改,缘于makeArray可以接受第二个参数(可以是数组或类数组,这时相当合并操作)
return jQuery.isArray( selector ) ?
this.setArray( selector ) ://内部用push方法,迅速将一个普通对象变成类数组对象
jQuery.makeArray( selector, this );
},

接着是广受欢迎的2010-02-13发布的1.42版
复制代码 代码如下:

init: function( selector, context ) {
var match, elem, ret, doc;
// 处理空白字符串,null,undefined参数
if ( !selector ) {
return this;
}
// 处理节点参数
if ( selector.nodeType ) {
this.context = this[0] = selector;
this.length = 1;
return this;
}
// 处理body参数(新增)
if ( selector === "body" && !context ) {
this.context = document;
this[0] = document.body;
this.selector = "body";
this.length = 1;
return this;
}
// 处理字符串参数,分七种情形:
//①单个标签,带对象属性包 ---> jQuery.merge
//②单个标签,不带对象属性包 ---> attr + jQuery.merge
//③复杂的HTML片断 ---> buildFragment + jQuery.merge
//④ID选择器,与找到的元素的ID不同 ---> getElementById + Sizzle + pushStack
//⑤ID选择器,与找到的元素的ID相同 ---> getElementById + 简单属性添加
//⑥标签选择器 ---> getElementsByTagName + jQuery.merge
//⑦其他CSS表达式 ---> Sizzle + pushStack
if ( typeof selector === "string" ) {
match = quickExpr.exec( selector );
if ( match && (match[1] || !context) ) {
if ( match[1] ) {
doc = (context ? context.ownerDocument || context : document);
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 = buildFragment( [ match[1] ], [ doc ] );
selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
}
return jQuery.merge( this, selector );
} else {
elem = document.getElementById( match[2] );
if ( elem ) {
if ( elem.id !== match[2] ) {
return rootjQuery.find( selector );
}
this.length = 1;
this[0] = elem;
}
this.context = document;
this.selector = selector;
return this;
}
} else if ( !context && /^\w+$/.test( selector ) ) {
this.selector = selector;
this.context = document;
selector = document.getElementsByTagName( selector );
return jQuery.merge( this, selector );
} else if ( !context || context.jquery ) {
return (context || rootjQuery).find( selector );
} else {
return jQuery( context ).find( selector );
}
// 处理函数参数,直接domReady
} else if ( jQuery.isFunction( selector ) ) {
return rootjQuery.ready( selector );
}
//处理jQuery对象参数
if (selector.selector !== undefined) {
this.selector = selector.selector;
this.context = selector.context;
}
//无论是数组还是类数组(如NodeList),统统使用jQuery.makeArray来为实例添加新的元素
return jQuery.makeArray( selector, this );
},

另附上makeArray方法与merge方法,merge方法好神奇啊,
复制代码 代码如下:

makeArray: function( array, results ) {
var ret = results || [];
if ( array != null ) {
// The window, strings (and functions) also have 'length'
// The extra typeof function check is to prevent crashes
// in Safari 2 (See: #3039)
if ( array.length == null || typeof array === "string" || jQuery.isFunction(array) || (typeof array !== "function" && array.setInterval) ) {
push.call( ret, array );
} else {
jQuery.merge( ret, array );
}
}
return ret;
},
merge: function( first, second ) {
var i = first.length, j = 0;
if ( typeof second.length === "number" ) {
for ( var l = second.length; j first[ i++ ] = second[ j ];
}
} else {
while ( second[j] !== undefined ) {
first[ i++ ] = second[ j++ ];
}
}
first.length = i;
return first;
},

2011-01-23发布的1.5版,其init方法与1.42的变化不大:只有两处做了改动:
复制代码 代码如下:

//1.42
- ret = buildFragment( [ match[1] ], [ doc ] );
- selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
//1.5
+ ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
+ selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes;
//1.42
- return jQuery( context ).find( selector );
//1.5
+ return this.constructor( context ).find( selector );//目的就是为了不再生成新实例

2011-05-02发布的jquery1.6,变化不大,只是对HTML片断进行了更严密的判定:
复制代码 代码如下:

// Are we dealing with HTML string or an ID?
if ( selector.charAt(0) === "" && selector.length >= 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 );
}

总体来说,jQuery的构造器已经做得非常之完美,基本上达到“改无可改”的地步了。但是要保证其高效运作,我们还需要一点选择器的知识与了解buildFragment方法的运作,因为这两个实在太常用了,但也是最耗性能的。
声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
在JavaScript中替换字符串字符在JavaScript中替换字符串字符Mar 11, 2025 am 12:07 AM

JavaScript字符串替换方法详解及常见问题解答 本文将探讨两种在JavaScript中替换字符串字符的方法:在JavaScript代码内部替换和在网页HTML内部替换。 在JavaScript代码内部替换字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 该方法仅替换第一个匹配项。要替换所有匹配项,需使用正则表达式并添加全局标志g: str = str.replace(/fi

8令人惊叹的jQuery页面布局插件8令人惊叹的jQuery页面布局插件Mar 06, 2025 am 12:48 AM

利用轻松的网页布局:8个基本插件 jQuery大大简化了网页布局。 本文重点介绍了简化该过程的八个功能强大的JQuery插件,对于手动网站创建特别有用

构建您自己的Ajax Web应用程序构建您自己的Ajax Web应用程序Mar 09, 2025 am 12:11 AM

因此,在这里,您准备好了解所有称为Ajax的东西。但是,到底是什么? AJAX一词是指用于创建动态,交互式Web内容的一系列宽松的技术。 Ajax一词,最初由Jesse J创造

10个JQuery Fun and Games插件10个JQuery Fun and Games插件Mar 08, 2025 am 12:42 AM

10款趣味横生的jQuery游戏插件,让您的网站更具吸引力,提升用户粘性!虽然Flash仍然是开发休闲网页游戏的最佳软件,但jQuery也能创造出令人惊喜的效果,虽然无法与纯动作Flash游戏媲美,但在某些情况下,您也能在浏览器中获得意想不到的乐趣。 jQuery井字棋游戏 游戏编程的“Hello world”,现在有了jQuery版本。 源码 jQuery疯狂填词游戏 这是一个填空游戏,由于不知道单词的上下文,可能会产生一些古怪的结果。 源码 jQuery扫雷游戏

如何创建和发布自己的JavaScript库?如何创建和发布自己的JavaScript库?Mar 18, 2025 pm 03:12 PM

文章讨论了创建,发布和维护JavaScript库,专注于计划,开发,测试,文档和促销策略。

使用AJAX动态加载盒内容使用AJAX动态加载盒内容Mar 06, 2025 am 01:07 AM

本教程演示了创建通过Ajax加载的动态页面框,从而可以即时刷新,而无需全页重新加载。 它利用jQuery和JavaScript。将其视为自定义的Facebook式内容框加载程序。 关键概念: Ajax和JQuery

jQuery视差教程 - 动画标题背景jQuery视差教程 - 动画标题背景Mar 08, 2025 am 12:39 AM

本教程演示了如何使用jQuery创建迷人的视差背景效果。 我们将构建一个带有分层图像的标题横幅,从而创造出令人惊叹的视觉深度。 更新的插件可与JQuery 1.6.4及更高版本一起使用。 下载

如何为JavaScript编写无曲奇会话库如何为JavaScript编写无曲奇会话库Mar 06, 2025 am 01:18 AM

此JavaScript库利用窗口。名称属性可以管理会话数据,而无需依赖cookie。 它为浏览器中存储和检索会话变量提供了强大的解决方案。 库提供了三种核心方法:会话

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热工具

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

功能强大的PHP集成开发环境