- 浏览: 27354 次
- 性别:
- 来自: 武汉
文章分类
最新评论
jQuery是web程序员的必备js库,估计90%以上的web项目都会用到它。今天周末,心血来潮,打算仔细瞧瞧其庐山真面目。记得以前也对其分析过一次,半途而废了,也没有记录下来。呵呵。废话少说,直接开始。高手请绕行,勿喷,有错误请指正。谢谢。
用eclipse打开jquery-1.11.1.js,源代码如下所示:
1. 在代码行的第一行的第一个左括号(的右边双击,定位到了代码的最后:
所以整个jquery源代码可以简化为:( ... ... );
就是一个小括号包含了一些javascript的表达式在里面。
2.我们再看看小括号里面是什么东西:
在第一行的第一个大括号{右边双击,通过代码定位知道了,这是一个匿名函数调用,可以简化为如下所示:
3.下面是最重要的:那么上面那个匿名函数的参数是什么呢?其参数的源代码如下:
很显然,第一个参数很简单:
就是全局对象window.
那么第二个参数呢?我们看到了function( window, noGlobal ) {,通过在大括号的右边双击,定位又到了代码的最后。所以第二个参数可以简化成如下所示:
所以第二个参数是一个函数,注意这里和上面的匿名函数调用不一样,这里没有调用,就是一个函数的定义,所以第二个参数就是一个函数,或者说函数句柄,也就是我们时时刻刻使用的jQuery,或者$,因为window.jQuery = window.$ = jQuery;。所以jQuery和$是等价的。
到了这里,那么整个代码就可以简化成如下:
这里window传给形参global,jQuery传给形参factory。
4. 我们把上面我们刚刚得到的简化结果在细化一下,通过阅读代码注释,知道
上面这个判断是为了适应CommonJS的环境。如果没有CommonJS环境,那么代码就是下面这个样子:
显然其实就等价于:jQuery(window);
上面的分析,只是理解了jquery中外边的一些枝节。最重要的是理解函数jQuery(window)的定义。
5. 上面我们说到了函数function( window, noGlobal ){... ...}就是jQuery的函数定义。
那么:jQuery(window);调用其实就是:jQuery(window, undefined);
也就是: function(window, undefined)();调用。
也就是说noGlobal 参数为的值为undefined.我们Ctrl+F在源代码中查找noGlobal 的有关情况:
所以函数function( window, noGlobal )的第二个参数用了noGlobal的含义是,是否将jQuery和$等价,并且赋值给全局对象window。[color=darkred]也就是决定了是否向全局变量中引入jQuery和$这两个全局变量[/color]。
所以如果在CommonJS环境中的话,并没有引入全局变量jQuery和$,而是仅仅将jQuery赋值给了module.exports:
也就是:module.exports = jQuery; 注意这里没有 $ 等价于 jQuery 了。
到了这里,jQuery源代码的外围枝节相关的代码已经分析完成。下面才是最核心的代码。
6. 下面开始看function( window, noGlobal ){... ...}的源代码:
最上面的几行代码应该是为将javascript中数组和对象的一些原生函数句柄赋值给jQuery 做准备的。
上面的代码明显:jQuery = new jQuery.fn.init( selector, context );
所以关键是jQuery.fn.init( selector, context );的定义。
在源代码中搜索:init 得到下面的代码:
所以:jQuery = function( selector, context ) { ... ...};
也就是jQuery函数就是根据:选择子selector在对应的上下文context中进行查找,找到之后将其构造成一个jQuery对象返回,这样可以就可以使用这个返回的jQuery对象所具有的各种函数了。其实大多数情况下,我们一般没有传递context改jQuery函数,那么默认context就是document了。最后一行代码:
return jQuery.makeArray( selector, this );
告诉我们,jquery是面向集合(数组)编程的,他返回的都是集合(数组)。
上面这103行代码才是jquery的核心。
对于上面核心代码的分析,下次在具体分析。
用eclipse打开jquery-1.11.1.js,源代码如下所示:
(function( global, factory ) { if ( typeof module === "object" && typeof module.exports === "object" ) { // For CommonJS and CommonJS-like environments where a proper window is present, // execute the factory and get jQuery // For environments that do not inherently posses a window with a document // (such as Node.js), expose a jQuery-making factory as module.exports // This accentuates the need for the creation of a real window // e.g. var jQuery = require("jquery")(window); // See ticket #14549 for more info module.exports = global.document ? factory( global, true ) : function( w ) { if ( !w.document ) { throw new Error( "jQuery requires a window with a document" ); } return factory( w ); }; } else { factory( global ); } // Pass this if window is not defined yet }(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { // Can't do this because several apps including ASP.NET trace // the stack via arguments.caller.callee and Firefox dies if // you try to trace through "use strict" call chains. (#13335) // Support: Firefox 18+ // var deletedIds = []; var slice = deletedIds.slice; ... ...
1. 在代码行的第一行的第一个左括号(的右边双击,定位到了代码的最后:
... ... // Expose jQuery and $ identifiers, even in // AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557) // and CommonJS for browser emulators (#13566) if ( typeof noGlobal === strundefined ) { window.jQuery = window.$ = jQuery; } return jQuery; }));
所以整个jquery源代码可以简化为:( ... ... );
就是一个小括号包含了一些javascript的表达式在里面。
2.我们再看看小括号里面是什么东西:
(function( global, factory ) {
在第一行的第一个大括号{右边双击,通过代码定位知道了,这是一个匿名函数调用,可以简化为如下所示:
(function( global, factory ) { ... ... }());
3.下面是最重要的:那么上面那个匿名函数的参数是什么呢?其参数的源代码如下:
// Pass this if window is not defined yet }(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
很显然,第一个参数很简单:
typeof window !== "undefined" ? window : this
就是全局对象window.
那么第二个参数呢?我们看到了function( window, noGlobal ) {,通过在大括号的右边双击,定位又到了代码的最后。所以第二个参数可以简化成如下所示:
function( window, noGlobal ) { ... ... if ( typeof noGlobal === strundefined ) { window.jQuery = window.$ = jQuery; } return jQuery; }
所以第二个参数是一个函数,注意这里和上面的匿名函数调用不一样,这里没有调用,就是一个函数的定义,所以第二个参数就是一个函数,或者说函数句柄,也就是我们时时刻刻使用的jQuery,或者$,因为window.jQuery = window.$ = jQuery;。所以jQuery和$是等价的。
到了这里,那么整个代码就可以简化成如下:
(function( global, factory ) { ... ... }(window, jQuery));
这里window传给形参global,jQuery传给形参factory。
4. 我们把上面我们刚刚得到的简化结果在细化一下,通过阅读代码注释,知道
if ( typeof module === "object" && typeof module.exports === "object" )
上面这个判断是为了适应CommonJS的环境。如果没有CommonJS环境,那么代码就是下面这个样子:
(function( global, factory ) { factory( global ); }(window, jQuery));
显然其实就等价于:jQuery(window);
上面的分析,只是理解了jquery中外边的一些枝节。最重要的是理解函数jQuery(window)的定义。
5. 上面我们说到了函数function( window, noGlobal ){... ...}就是jQuery的函数定义。
那么:jQuery(window);调用其实就是:jQuery(window, undefined);
也就是: function(window, undefined)();调用。
也就是说noGlobal 参数为的值为undefined.我们Ctrl+F在源代码中查找noGlobal 的有关情况:
function( window, noGlobal ){ // General-purpose constants strundefined = typeof undefined, ... ... if ( typeof noGlobal === strundefined ) { window.jQuery = window.$ = jQuery; } return jQuery; }
所以函数function( window, noGlobal )的第二个参数用了noGlobal的含义是,是否将jQuery和$等价,并且赋值给全局对象window。[color=darkred]也就是决定了是否向全局变量中引入jQuery和$这两个全局变量[/color]。
所以如果在CommonJS环境中的话,并没有引入全局变量jQuery和$,而是仅仅将jQuery赋值给了module.exports:
module.exports = global.document ? factory( global, true ) :function( w ) {};
也就是:module.exports = jQuery; 注意这里没有 $ 等价于 jQuery 了。
到了这里,jQuery源代码的外围枝节相关的代码已经分析完成。下面才是最核心的代码。
6. 下面开始看function( window, noGlobal ){... ...}的源代码:
function( window, noGlobal ) { var deletedIds = []; var slice = deletedIds.slice; var concat = deletedIds.concat; var push = deletedIds.push; var indexOf = deletedIds.indexOf; var class2type = {}; var toString = class2type.toString; var hasOwn = class2type.hasOwnProperty; var support = {}; var version = "1.11.1", // Define a local copy of jQuery jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' // Need init if jQuery is called (just allow error to be thrown if not included) return new jQuery.fn.init( selector, context ); }, ... ...
最上面的几行代码应该是为将javascript中数组和对象的一些原生函数句柄赋值给jQuery 做准备的。
上面的代码明显:jQuery = new jQuery.fn.init( selector, context );
所以关键是jQuery.fn.init( selector, context );的定义。
在源代码中搜索:init 得到下面的代码:
init = jQuery.fn.init = function( selector, context ) { var match, elem; // HANDLE: $(""), $(null), $(undefined), $(false) if ( !selector ) { return this; } // Handle HTML strings 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 { 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; // 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 ) ); // HANDLE: $(html, props) if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { for ( match in context ) { // 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; // 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: $(DOMElement) } else if ( selector.nodeType ) { this.context = this[0] = selector; this.length = 1; return this; // HANDLE: $(function) // Shortcut for document ready } else if ( jQuery.isFunction( selector ) ) { return typeof rootjQuery.ready !== "undefined" ? rootjQuery.ready( selector ) : // Execute immediately if ready is not present selector( jQuery ); } if ( selector.selector !== undefined ) { this.selector = selector.selector; this.context = selector.context; } return jQuery.makeArray( selector, this ); };
所以:jQuery = function( selector, context ) { ... ...};
也就是jQuery函数就是根据:选择子selector在对应的上下文context中进行查找,找到之后将其构造成一个jQuery对象返回,这样可以就可以使用这个返回的jQuery对象所具有的各种函数了。其实大多数情况下,我们一般没有传递context改jQuery函数,那么默认context就是document了。最后一行代码:
return jQuery.makeArray( selector, this );
告诉我们,jquery是面向集合(数组)编程的,他返回的都是集合(数组)。
上面这103行代码才是jquery的核心。
对于上面核心代码的分析,下次在具体分析。
发表评论
-
深入理解javascript语言中的this
2014-12-07 11:46 1215说到js中的函数中的this指针,就像是悟空的毫毛一样,可以随 ... -
javascript中函数作用域和全局作用域
2014-12-03 17:41 972在地址:http://www.cnblogs.com/shar ... -
关于编写性能高效的javascript事件的技术
2014-12-03 11:00 516转自:http://www.cnblogs.com/sharp ... -
javascript中如何声明一个全局对象
2014-12-02 21:23 666一般我们都知道直接在任何方法外面使用var关键字声明的变量就是 ... -
阿里淘宝的js命名空间函数namespace
2014-12-02 18:47 1011在使用阿里开源的druid数据库连接池时,发现它的jar包中包 ... -
JSTL标签遍历map list
2014-11-25 17:47 3233使用jsp的标签库,遍历一个元素为map的List: List ... -
jquery绑定事件失效的情况
2014-11-20 21:15 2357现在的web项目,不使用j ... -
编写更好的jQuery代码的建议
2013-12-10 10:22 692讨论jQuery和javascript性能的文章并不罕见。然而 ... -
submit表单使用javascript函数控制提交
2013-11-01 13:09 1546为了说明情况,下面的代码是经过简化的演示: <in ... -
javascript的执行并非完全同步
2013-11-01 13:08 0为了说明情况,下面的代码是经过简化的演示: <in ... -
input 为disabled 引起的java.lang.NullPointerException
2013-10-31 10:47 1458最近遇到一个空指针异常: 严重: Servlet.serv ...
相关推荐
压缩后的`jquery-1.11.1.min.js`通过删除注释、合并变量、压缩代码等方式,显著减少了文件大小,提高了页面加载速度。然而,由于代码被高度压缩,不适合用于调试,因为其可读性较差。 8. **使用场景** jQuery广泛...
《jQuery 1.11.1.js与2.11.1.js:核心差异与应用场景》 jQuery,作为一款广泛使用的JavaScript库,极大地简化了DOM操作、事件处理、动画效果和Ajax交互。本文将深入探讨jQuery 1.11.1.js和2.11.1.js两个版本的核心...
《jQuery 1.11.1 2014最新版中文API——深入解析与实践指南》 jQuery,作为一款广泛应用于Web开发的JavaScript库,以其简洁、易用的API和强大的功能,深受开发者喜爱。在2014年发布的jQuery 1.11.1版本,是该库的一...
《jQuery库:深入理解jquery-1.11.1.js与jquery-1.11.1.min.js》 在Web开发领域,jQuery是一款极其重要的JavaScript库,它极大地简化了JavaScript的DOM操作、事件处理、动画设计和Ajax交互。标题中的"jquery-1.11.1...
在源代码中,你可以看到详细的函数定义和注释,这对于学习和调试jQuery的内部工作原理非常有帮助。 其次,`jquery-1.11.1.min.js` 是压缩版本的jQuery库。这个文件经过了最小化处理,去除了不必要的空格、换行和...
**jQuery 1.11.1 和 jQuery 1.7.2:JavaScript 库的核心特性与差异** jQuery 是一个广泛使用的 JavaScript 库,它极大地简化了网页中的 DOM 操作、事件处理、动画制作以及Ajax交互。jQuery 的核心理念是“Write ...
jQuery库
《jQuery 1.11.1:Web开发的利器》 jQuery,作为一款广泛应用于Web开发的JavaScript库,因其简洁的API和强大的功能而深受开发者喜爱。本篇将深入探讨jQuery 1.11.1版本的核心特性、优势以及如何在实际项目中应用。 ...
好用的jquery源码,完善了老版本的很多问题,切添加了许多新的功能。
本次提供的有:jquery-1.11.1.js、jquery-1.11.1.min.js、jquery-2.1.1.js和jquery-2.1.1.min.js。 说明: 1、文件名中包含min字样的为压缩版。2、压缩版本适于实际应用,未压缩版本适于开发调试过程。 3、2.x版本...
资源名称:jQuery 中文手册 1.11.1内容简介:jquery中文手册 自从 2011 第1.7版到现在,这期间进行了很多次修改,因为作者相信:只要用心,哪怕一个小玩意都可以做到极致。 jQuery API 1.4.4 是一部比较详细的中文...
而`jquery.js`是未压缩的源代码,便于开发者阅读和调试。 6. **兼容性与性能**: jQuery 1.11.x系列对老版本的浏览器有着良好的支持,包括IE6/7/8。但随着浏览器的更新迭代,开发者在考虑性能和现代特性时,可能会...
未压缩的jQuery1.11.js,可以查看源代码
jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
《jQuery 1.11.1 API 深度解析》 jQuery,作为一款轻量级的JavaScript库,因其简洁的语法和强大的功能,自2006年发布以来,一直备受开发者喜爱。jQuery 1.11.1是其在1.x版本线上的一个重要更新,它提供了一整套API...
jQuery 1.11.1.min.js是jQuery库的一个压缩和优化版本,"minified"意味着代码经过了压缩处理,去除了不必要的空格、注释和换行,以减小文件大小,提高页面加载速度。这一版本发布于2014年,旨在提供稳定性和性能优化...
1. **jQuery核心库**: `jquery-1.11.1.js`是未压缩的、未优化的源代码版本,主要用于开发环境。它包含了完整的调试信息和可读性强的代码,便于开发者查看和理解内部逻辑,这对于学习和调试非常有用。 2. **压缩版...
jquery-1.11.1.min.js d