前記:
想系統的好好寫寫,但是會先從感興趣的部分開始。
近期有讀者把pdf傳到了百度文庫上,首先感謝轉載和傳播,但是據為已有并設定了挺高的财富值才能下載下傳就不好了,以後我整理好了會傳到文庫上。請體諒一下。
3. 構造jquery對象
先看看總體結構,再做分解:
<col>
(function( window, undefined ) {
var jquery = (function() {
// 建構jquery對象
var jquery = function( selector, context ) {
return new jquery.fn.init( selector, context, rootjquery );
}
// jquery對象原型
jquery.fn = jquery.prototype = {
constructor: jquery,
init: function( selector, context, rootjquery ) {
// selector有以下7種分支情況:
// dom元素
// body(優化)
// 字元串:html标簽、html字元串、#id、選擇器表達式
// 函數(作為ready回調函數)
// 最後傳回僞數組
}
};
// give the init function the jquery prototype for later instantiation
jquery.fn.init.prototype = jquery.fn;
// 合并内容到第一個參數中,後續大部分功能都通過該函數擴充
// 通過jquery.fn.extend擴充的函數,大部分都會調用通過jquery.extend擴充的同名函數
jquery.extend = jquery.fn.extend = function() {};
// 在jquery上擴充靜态方法
jquery.extend({
// ready bindready
// isplainobject isemptyobject
// parsejson parsexml
// globaleval
// each makearray inarray merge grep map
// proxy
// access
// uamatch
// sub
// browser
});
// 到這裡,jquery對象構造完成,後邊的代碼都是對jquery或jquery對象的擴充
return jquery;
})();
window.jquery = window.$ = jquery;
})(window);
l jquery對象不是通過 new jquery 建立的,而是通過 new jquery.fn.init 建立的
var jquery = function( selector, context ) {
return new jquery.fn.init( selector, context, rootjquery );
}
n jquery對象就是jquery.fn.init對象
n 如果執行new jqeury(),生成的jquery對象會被抛棄,最後傳回 jquery.fn.init對象;是以可以直接調用jquery( selector, context ),沒有必要使用new關鍵字
l 先執行 jquery.fn = jquery.prototype,再執行 jquery.fn.init.prototype = jquery.fn,合并後的代碼如下:
jquery.fn.init.prototype = jquery.fn = jquery.prototype
所有挂載到jquery.fn的方法,相當于挂載到了jquery.prototype,即挂載到了jquery 函數上(一開始的 jquery = function( selector, context ) ),但是最後都相當于挂載到了jquery.fn.init.prototype,即相當于挂載到了一開始的jquery 函數傳回的對象上,即挂載到了我們最終使用的jquery對象上。
這個過程非常的繞,金玉其外“敗絮”其中啊!
jquery.fn.init的功能是對傳進來的selector參數進行分析,進行各種不同的處理,然後生成jquery對象。
類型(selector)
處理方式
dom元素
包裝成jquery對象,直接傳回
body(優化)
從document.body讀取
單獨的html标簽
document.createelement
html字元串
document.createdocumentfragment
#id
document.getelementbyid
選擇器表達式
$(…).find
函數
注冊到dom ready的回調函數
// 合并兩個或更多對象的屬性到第一個對象中,jquery後續的大部分功能都通過該函數擴充
// 通過jquery.fn.extend擴充的函數,大部分都會調用通過jquery.extend擴充的同名函數
// 如果傳入兩個或多個對象,所有對象的屬性會被添加到第一個對象target
// 如果隻傳入一個對象,則将對象的屬性添加到jquery對象中。
// 用這種方式,我們可以為jquery命名空間增加新的方法。可以用于編寫jquery插件。
// 如果不想改變傳入的對象,可以傳入一個空對象:$.extend({}, object1, object2);
// 預設合并操作是不疊代的,即便target的某個屬性是對象或屬性,也會被完全覆寫而不是合并
// 第一個參數是true,則會疊代合并
// 從object原型繼承的屬性會被拷貝
// undefined值不會被拷貝
// 因為性能原因,javascript自帶類型的屬性不會合并
// jquery.extend( target, [ object1 ], [ objectn ] )
// jquery.extend( [ deep ], target, object1, [ objectn ] )
jquery.extend = jquery.fn.extend = function() {
var options, name, src, copy, copyisarray, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;
// handle a deep copy situation
// 如果第一個參數是boolean型,可能是深度拷貝
if ( typeof target === "boolean" ) {
deep = target;
target = arguments[1] || {};
// skip the boolean and the target
// 跳過boolean和target,從第3個開始
i = 2;
}
// handle case when target is a string or something (possible in deep copy)
// target不是對象也不是函數,則強制設定為空對象
if ( typeof target !== "object" && !jquery.isfunction(target) ) {
target = {};
// extend jquery itself if only one argument is passed
// 如果隻傳入一個參數,則認為是對jquery擴充
if ( length === i ) {
target = this;
--i;
for ( ; i < length; i++ ) {
// only deal with non-null/undefined values
// 隻處理非空參數
if ( (options = arguments[ i ]) != null ) {
// extend the base object
for ( name in options ) {
src = target[ name ];
copy = options[ name ];
// prevent never-ending loop
// 避免循環引用
if ( target === copy ) {
continue;
}
// recurse if we're merging plain objects or arrays
// 深度拷貝且值是純對象或數組,則遞歸
if ( deep && copy && ( jquery.isplainobject(copy) || (copyisarray = jquery.isarray(copy)) ) ) {
// 如果copy是數組
if ( copyisarray ) {
copyisarray = false;
// clone為src的修正值
clone = src && jquery.isarray(src) ? src : [];
// 如果copy的是對象
} else {
clone = src && jquery.isplainobject(src) ? src : {};
}
// never move original objects, clone them
// 遞歸調用jquery.extend
target[ name ] = jquery.extend( deep, clone, copy );
// don't bring in undefined values
// 不能拷貝空值
} else if ( copy !== undefined ) {
target[ name ] = copy;
// return the modified object
// 傳回更改後的對象
return target;
};
未完待續
from:http://nuysoft.iteye.com/blog/1182087