第一課 jQuery的整體結構(一)
一.文檔內容以圍繞以下兩個方面進行
1. jQuery代碼的機制; ——表現形式或者是使用方法
2. jQuery原理的函數實現過程; ——代碼實現
二.學習要求
1. 要有相關javascript的基礎知識,例如:閉包作用域、promise異步、原型等等;
2. 相關DOM操作的基礎知識;
3. 會正則表達式;
三.源碼下載
源碼下載步驟:
1. 進入jQuery官網:www.jQuery.com ;
2. 點擊 Download進入下載頁;
3. 有一下兩個版本(注:這邊的版本可能落後於現在的版本了,因爲作者學習的視屏中的版本是很早之前的版本,所以這邊提供了之前版本的下載地址,並且本套筆記中均使用 jQuery 2.0.3 進行配套講解)
(1) jQuery 1.10.2
(2) jQuery 2.0.3
四.jQuery 1.10.2與jQuery2.0.3兩個版本的區別
jQuery從2.x版本開始就不再支持IE6、IE7和IE8的瀏覽器版本了。對應的只支持比較高級的瀏覽器版本。
↓
這樣做的好處:
可以減少一些兼容性的寫法,減少hack的寫法的代碼
↓
所以我們下面文檔的講解均以 jQuery 2.0.3爲參考進行講解。
五.jQuery整體結構速覽
使用Microsoft Visual Studio 2015對 jQuery 2.0.3.js 打開(當然也可以使用DreamWare或者是WebStorm等的軟件進行打開,博主比較喜歡用vs來寫),這裏不使用jQuery的min版本,因爲min版本e中有變量的簡寫以及不存在換行,不便於用作學習。
打開後可以看到一共有8830行的代碼。如下圖所示:
我們先整理 jQuery的整體框架(簡化框架)
(1)先看第14行:
如下圖所示:
(function( window, undefined ) {
//jQuery內核代碼
})( window );
<1>對於第14行開始的“ function( window, undefined ){ ”是一個匿名數,而對於在8829行的“ })(window)”則是對14行這個匿名函數的“自執行”調用;
※那麼,這樣寫有什麼好處嗎?
學過函數作用域的都應該知道函數的作用域。在匿名函數裏面寫的東西都會是局部的,在外面無法訪問,防止了定義的變量和函數對外部空間的“污染”,體現了面向對象的原則。
例如:
(function(){
var a=10;
function $()
{
alert(a);
};
})();
alert(a);//定義的變量a無法再外部使用
$(); //定義的函數也沒有辦法在外部使用
在上面的代碼中
對於“ alert(a); ”和“ $(); ”的執行結果分別爲 “ ‘a’ is undefined !” 和“ ‘$’ is undefined function!”;
※那麼如何才能在外部代碼中可以訪問匿名函數中的變量和函數呢?
其實,有很多的方法是可以做到的。例如把你需要調用的變量和函數掛載到window對象上,例如如下代碼:
( function() {
var a=10;
function $()
{
alert(a);
};
window.$=$;
})();
$(); //調用會彈出alert彈窗並顯示10
或者
( function(widowObj) { //爲了體現是傳遞參數,這邊就寫成windowObj
var a=10;
function $()
{
alert(a);
};
widowObj.$=$;
})(window);
$(); //調用會彈出alert彈窗並顯示10
在jQuery中是按照上面給出的第二種進行傳參掛載的。
首先我們要先了解一下:
jQuery=function(...){...}
【1】我們平時使用的" $ "或者“ jQuery ”都是上面的聲明的變量;
【2】那麼我們爲什麼可以訪問到它呢?
答:和前面的匿名自執行一樣。他把內部的" $ "或者“ jQuery ”在傳入的window對象上進行掛載。
(2)看到程序代碼第8825-8827行:
if ( typeof window === "object" && typeof window.document === "object" ) {
window.jQuery = window.$ = jQuery;
}
這裏便是將" $ "和" jQuery "進行掛載。首先,它先判斷了一下,傳入的window是不是一個有document文檔節點的對象。這邊由於我們網頁中的window對象中自帶document對象,所以做這樣的判斷。
(3)看到第96行:
jQuery.fn = jQuery.prototype = {...}
上面的代碼" jQuery.prototype "是 jQuery對象的原型,它是一個面向對象的概念,所以 jQuery是一個基於面向對象(Object Oriented)的語言。
※從使用的角度看,爲什麼 jQuery是一個面向對象的語言?
首先我們看一下普通的面向對象:
對於一個數組對象
var arr = new Array();
arr.push();
arr.sort();
上面可以看到push和sort方法之所以可以調用,是因爲arr是一個數組的對象,對象中有定義的對應的方法來控制和處理對象。
那麼,類似的,我們看一下 jQuery對象
$('#div').css('background-color','red');
$('#div').html('<div>這是一個div</div>');
上面的css和html方法之所以可以調用,是因爲" $('#div') "的執行結果是返回一個 jQuery對象。
(4)看到第61-64行代碼:
// Define a local copy of jQuery
jQuery = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context, rootjQuery );
},
在 jQuery中由於掛載的定義我們可以知道" $(...) "等價於" jQuery(...) ",只是我們平時爲了書寫方便,所以多用" $ "符號的形式。對於jQuery的定義我們可以看到,它其實是一個函數的標識符,它代表的是一個函數對象。那麼執行" $(...) "其實是在執行一個函數方法。在看到對於這個匿名函數,它有一個返回值" return new jQuery.fn.init( selector, context, rootjQuery ) ",它是一個用new關鍵字調用構造函數返回對象的過程,從此也可以知道 jQuery是一門面向對象的語言。
(5)看到第285行:
jQuery.extend = jQuery.fn.extend = function() {...}
上面的代碼,其實是定義了jQuery的繼承方法。
目的:jQuery的開發者希望後續添加的代碼,都可以通過extend掛載到 jQuery對象中,這樣做可以比較方便的進行擴展,而不是一上來就把所有的方法寫到一起,而不利於代碼的後期的獨立性、擴展性和可維護性。即,繼承可以方便後期的插件擴展。
(6)看到第349行:
jQuery.extend({
...
});
首先,這裏用的就是上面對繼承方法的定義的使用。它定義了一些工具方法。
★★★下面我們要理清一些基本的概念 ★★★:
<1> jQuery中提供了兩種操作代碼的方式:
操作代碼的方式 | 操作類型 | 所屬方法類型 | 例子 |
方式一 | 使用選擇器 | 對象,對象方法(); | $('#div').html(); 也可以寫作爲 jQuery('#div').html(); |
方式二 | 直接使用 jQuery對象 | 靜態方法();(純函數的方法) | $.trim(); $.proxy(); 也可以寫作 jQuery.trim(); jQuery.proxy(); |
在 jQuery中,來給面向對象進行擴展靜態屬性和靜態方法的過程,我們稱之爲"擴展工具方法"。
<2> jQuery的對象方法與擴展工具方法的區別:
【1】擴展的工具方法,它既可以給 jQuery對象來使用,有可以給原生的javaScript的代碼來進行使用;
【2】而像css和html這類的 jQuery對象方法,只能給 jQuery對象來使用;
<3>擴展這些工具方法是爲了便於 jQuery自身或者是用戶在後期可以使用,使得一些處理過程進行簡化、複用。
※那麼靜態方法和對象方法之間的關係究竟是什麼呢?
如下圖:
(7)jQuery的框架圖:
代碼所在的程序行數 | 對應的代碼段的功能梗概 |
0~20 |
( function (){ |
21~94 | 定義了一些變量和函數,重點:jQuery=function(...){...} |
96~283 | 給jQuery對象添加一些方法和屬性 |
285~347 | extend:jQuery的繼承方法 |
349~817 | jQuery.extend():擴展一些工具方法 |
... | ... |
8826 | window.jQuery=window.$=jQuery:jQuery對象掛載 |
最後 | })(); |