javascript笔记:临摹jQuery(一)
多年的软件开发经验让我知道,做技术不管怎么看都不如做一下,就算是读源码,也不应该只是读,更多还是动手练习,做的时候身临其境体会大师们设计的巧妙。
临摹就是一个很不错的练习方式,大学读书时候我的专业是工业设计,大一大二有很多素描色彩课,那时候老师总是布置临摹的作业,当时自己悟性太低,把临摹当做抄袭,很少动脑筋去思考临摹到底是咋回事,现在做软件了,想临摹jQuery的框架时候才发现,这是件非常困难的事情,真正的临摹是要领悟作者的思路,只有理解了作者为什么这么做,才知道如何去临摹作者的作品。
好了不说这些华而不实的大话了。上篇博文里我通过学习javascript正则表达式,读了下jQuery里面选择造器的代码,通过传入到jQuery里面参数的不同,分析了下jQuery选择器整个代码的运行,但是如果只是做到这些,上篇文章的大众意义就比较差了,很难让人理解jQuery到底为什么会设计选择器,选择器在jQuery里的地位等等。所以前一篇对jQuery源码的分析有点断章取义,所以我今天查阅了一些资料,也静下心来好好琢磨了下jQuery的框架,根据以前调试程序的经验,我想深入理解jQuery,第一步就是要明白jQuery对象是如何构造的。
我研究的主要是jquery-1.4.1.js,这是我使用最多的一个版本,而且我经常使用的帮助文档也是这个版本的,另外一个是jquery-1.6.1.js,这个做为1.4.1的配合版本,通过比较二者差异来体会作者在改进jquery的着力点在哪里,其次我手头的资料都是用jquery-1.2.x.js作为分析对象。我临摹时候讲jQuery的名称改为了xQuery,意思是扩展的jQuery,也标示它和原始的jQuery的某些不同(不同是指有时候我会根据代码的特点,讲1.4.1和1.61的代码进行混搭)。代码如下:
(注意:我写的代码要在装有firebug的firefox里面运行)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" > <html xmlns= "http://www.w3.org/1999/xhtml" > <head> <meta http-equiv= "Content-Type" content= "text/html; charset=utf-8" /> <title> xQuery study</title> <script type= "text/javascript" > ( function (window,undefined){ var document = window.document,navigator = window.navigator,location = window.location; var xQuery = function (selector,context){ return new xQuery.fn.init(selector,context); }, // 检测HTML代码,ID表达式 quickExpr = /^[^<]*(<[\w\W]+>)[^>]*$|^ #([\w-]+)$/; xQuery.fn = xQuery.prototype = { constructor:xQuery, init: function (selector,context){ var match,elem,ret,doc; //xQuery(''),xQuery(null),or xQuery(undefined); if (!selector) { return this ; } //xQuery(DOMElement) if (selector.nodeType) { this .context = this [0] = selector; this .length = 1; return this ; } // body元素在页面里面只会有一个,没必要遍历DOM进行查找,这是一个优化 // 写法,我是在jquery-1.6.1.js里面有下面的写法 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' ) { //首先我们要确定我们处理的字符串到底是HTML代码还是ID表达式 //在jquery-1.6.1里面,增加了一个对传入字符串开始结束字符是否都是 // <>的判断,如果是的话就不做正则表达式的校验了 if (selector.charAt(0) === "<" && selector.charAt(selector.length-1) === '>' && selector.length >= 3) { match = [ null , selector, null ]; //match里面的值,参见我前一篇博文 } else { match = quickExpr.exec( selector ); } //quickExpr.exec( selector );表达式执行的结果(详细解释参见上一篇博文) //只有当selector字符是带有#号前缀字符串或者是字符串里包含有用<>包含的字符串时候 //match才不能为空,当selector是带#号的字符串时候,match[1]==undefined,而包含有 //用<>包含的字符串的时候match[1]是不为空的,因此下面的if...else...就清晰了 //注意:我研究的前提都是在context为空的情况下,因此!context一直都是true if (match && (match[1] || !context)) //当match不为空,在我研究前提下这个总为true { //这个if就是匹配上了有HTML语句以及有带#号的字符串的情况 if (match[1]) //HTML语句 { //这里的代码我现在还没读懂,所以不提供代码,统一返回this return this ; } else { //xQuery("#id")的情况 //这里面的代码取自jquery-1.6.1 elem = document.getElementById(match[2]); //下面是针对IE和Opera浏览器下的特别处理,因为在这两个浏览器的某些版本里 //document.getElementById有可能用name替代了ID if ( elem && elem.parentNode ) { // 在1.4.1里面是没有&& elem.parentNode,注释说这是针对黑莓手机的处理 //看来jQuery的触角已经延伸到了手机领域了,等我研究完javascript就研究 //android,那时再瞧瞧这些 if ( elem.id !== match[2] ) { //return rootjQuery.find( selector ); //find方法还没仔细阅读,因此不提供代码,统一返回this return this ; } this .length = 1; this [0] = elem; } this .context = document; this .selector = selector; return this ; } } else if (!context && /^\w+$/.test( selector )){ //这个是xQuery('div'),字符串是HTML标签 // 对于HTML标签是直接使用document.getElementsByTagName,但是这时候并没有返回jQuery对象 // 代码还会走到if (!context || context.xquery)里面再进行返回 this .selector = selector; this .context = document; selector = document.getElementsByTagName( selector ); } else if (!context || context.xquery) { //xQuery('div .red'),xQuery('div')最终也是走到这个里面再进行return //return (context || rootjQuery).find( selector ); //find方法还没仔细阅读,因此不提供代码,统一返回this return this ; } else { //这个else是针对这样的情况xQuery(expr, context),就是context不为空的情况 //return jQuery( context ).find( selector ); //find方法还没仔细阅读,因此不提供代码,统一返回this return this ; } } //其他代码省略,主要还没深入到某些jQuery方法里面,对某些方法的源码理解不够,这边先不写了 return this ; //其他情况统一返回jQuery对象 }, selector: "" , xquery: "1.0" , length:0, size: function (){ return this .length; } }; xQuery.fn.init.prototype = xQuery.fn; window.xQuery = window.$ = xQuery; })(window); function main() { console.log(xQuery( '' )); console.log(xQuery( null )); console.log(xQuery(undefined)); console.log(xQuery( '' ).xquery); console.log(xQuery( '' ) instanceof xQuery); console.log(xQuery( '#txt01' )); console.log(xQuery( '#txt01' )[0].value); console.log(xQuery(document.getElementById( 'txt01' ))); console.log(xQuery(document.getElementById( 'txt01' ))[0].value); } //window.onload = main();//error </script> </head> <body> <form> <input type= "text" id= "txt01" name= "txt01" value= "Test xQuery" /> <input type= "button" value= "BTN" onclick= "main()" /> </form> </body> </html> |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" > <html xmlns= "http://www.w3.org/1999/xhtml" > <head> <meta http-equiv= "Content-Type" content= "text/html; charset=utf-8" /> <title>jQuery Test</title> </head> <body> <form> <input type= "text" id= "txt01" name= "txt01" value= "Test xQuery" /> <input type= "button" value= "BTN" onclick= "main()" /> </form> </body> </html> <script src= "jquery-1.4.1.js" ></script> <script type= "text/javascript" > function main() { console.log(jQuery( '' )); console.log(jQuery( null )); console.log(jQuery(undefined)); console.log(jQuery( '' ).jquery); console.log(jQuery( '' ) instanceof jQuery); console.log(jQuery( '#txt01' )); console.log(jQuery( '#txt01' )[0].value); console.log(jQuery(document.getElementById( 'txt01' ))); console.log(jQuery(document.getElementById( 'txt01' ))[0].value); } </script> |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· [AI/GPT/综述] AI Agent的设计模式综述