jQuery 是一款开源的,最流行的,面向对象的Javascript框架,因为平时经常使用,也就萌生了阅读源码的想法,尝试着去分析一下,如果有问题,还请大家指点。
阅读 jQuery 源码之前,必须要了解 jQuery 的工作机制,在我看来,实际上 jQuery 是一个标准的以面向对象的程序结构,jQuery 本身是一个类,而每一个我们构建的 jQuery 对象则是这个类实例。
因此我从如下两个方法来入手
1、如何构造 jQuery 对象
2、jQuery对象的继承
1、如何构造 jQuery 对象
jQuery 提供了四种封装jQuery对象的方法,分别是
- DOMElement
- HTML strings
- TAG
- expr, $(…)
这四种方法的调用如下。
elem = document.getElementsByTagName("div"); elem = $(elem);
var elem = $("<p>hello</p>");
var elem = $("div");
var elem = $("body > div");
通过这些方法,就生成一个jQuery对象。
那么,在jQuery内部,是如何去封装这个对象的呢?
看代码
var jQuery = function( selector, context ) { // 创建一个自定义对象,并返回 return new jQuery.fn.init( selector, context ); }
不难理解,jQuery 对象实际上通过new运算符创建的一个继承jQuery.prototype.init()返回的对象的原型的对象。
让我们简化jQuery.fn.init方法,并看看他是如何去运作的
jQuery.fn = jQuery.prototype = { init: function( selector, context ) { var match, elem, ret, doc; // 如果选择器为空、null、undefined的时候,返回 jQuery对象 if ( !selector ) { return this; } // Handle $(DOMElement) if ( selector.nodeType ) { // 如果选择器为DOM对象,写入jQuery属性并返回jQuery对象 this.context = this[0] = selector; this.length = 1; return this; } // The body element only exists once, optimize finding it if ( selector === "body" && !context ) { //code here... return this; } // Handle HTML strings if ( typeof selector === "string" ) { // 通过正则判断传入的选择器是HTML字符串还是ID // Are we dealing with HTML string or an ID? // quickExpr = /^[^< ]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/, match = quickExpr.exec( selector ); // 如果match[1]不为空或者context为空的时候 if ( match && (match[1] || !context) ) { // HANDLE: $(html) -> $(array) // 如果match[1] 不为空(html字符串) if ( match[1] ) { // 返回jQuery、选择器两数组合并后的对象 return jQuery.merge( this, selector ); // HANDLE: $("#id") // 如果context为空的时候 (id) } else { // 尝试按照DOM节点的方式返回jQuery对象 elem = document.getElementById( match[2] ); if ( elem ) { // 如果得到elem对象,但id非match[2] 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: $("TAG") // 如果context为空并且是一个纯字母的字符串 } else if ( !context && /^\w+$/.test( selector ) ) { // 返回jQuery、选择器两数组合并后的对象 return jQuery.merge( this, selector ); // HANDLE: $(expr, $(...)) // 如果context为空 或者 context是一个jQuery对象 } else if ( !context || context.jquery ) { // 在上下文或者document对象中找到节点并返回jQuery对象 return (context || rootjQuery).find( selector ); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return jQuery( context ).find( selector ); } // HANDLE: $(function) // Shortcut for document ready // 对$(document).ready(functon(){});的一个缩写$(function(){}); } else if ( jQuery.isFunction( selector ) ) { return rootjQuery.ready( selector ); } // 如果选择器是一个jQuery对象,引用下 if (selector.selector !== undefined) { this.selector = selector.selector; this.context = selector.context; } return jQuery.makeArray( selector, this ); } }
至此,我们就完成了对jQuery对象的构造。
2、jQuery对象的继承
当我们构造完成jQuery对象后,需要jQuery对象继承jQuery中的方法与属性。
看代码
jQuery.fn.init.prototype = jQuery.fn;
如此,就将jQuery的原型赋到jQuery对象的原型上去了,jQuery对象就继承了jQuery初始的方法和属性。
那么,当我需要向已实例化的对象原型中增加方法或者属性怎么办?
这就需要用到扩展方法 –> extend
下次接着说~
