[No.6 jQuery源碼解析—逐段解析(6)


繼續咱們的jQuery源碼解析。

(function(){

? ? ? ?

原文中此處為鏈接,暫不支持采集

? ? ? ? (96?,?283)?給JQ對象添加一些方法和屬性

? ? ? ? (285?,?347)?extend?:?JQ的繼承方法

? ? ? ? (349?,?817)?jQuery.extend() :?擴展一些工具方法

????????(877?,?2856) ?Sizzle?:?復雜選擇器的實現

? ? ? ? (2880?,?3042)?Callbacks?:?回調對象?:?對函數的統一管理

? ? ? ? (3043?,?3183)?Deferred?:?延遲對象?:?對異步的統一管理

? ? ? ? (3184?,?3295)?support?:?功能檢測

? ? ? ? (3308?,?3652)?data() :?數據緩存

? ? ? ? (3653?,?3797)?queue() :?隊列方法?:?執行順序的管理

? ? ? ? (3803?,?4299)?attr()?prop()?val()?addClass()?:?對元素屬性的操作

? ? ? ? (4300?,?5128)?on()?trigger() :?事件操作的相關方法

? ? ? ? (5140?,?6057)?DOM操作?:?添加?刪除?獲取?包裝?DOM篩選

? ? ? ? (6058?,?6620)?css() :?樣式的操作

? ? ? ? (6621?,?7854)?提交的數據和ajax() :?ajax()?load()?getJSON()

? ? ? ? (7855?,?8584)?animate() :?運動的方法

? ? ? ??(8585?,?8792)?offset() :?位置和尺寸的方法

? ? ? ??(8804?,?8821)?JQ支持模塊化的模式

? ? ? ? (8826) ?window.jQuery?=?window.$?=?jQuery;

? ? })();


第一部分,已經簡單地分析完畢了,

當我分析完的代碼,我都會在前面打'

原文中此處為鏈接,暫不支持采集

',

說明咱們這一塊已經讀完,

大家也可以直接點擊跳轉相應的內容,

接下來,咱們來看第二塊,

第二部分,差不多200行代碼,

這一塊兒是干嘛的呢?

這一塊就是給jQuery添加一些常用的屬性和方法,

其實我們知道jQuery就是基于面向對象的程序,

所以說面向對象就離不開來屬性和方法,

這一塊,我也給它進行了簡化處理,

我們先來看一下這個簡化的代碼。

<script>

? ? jQuery.fn = jQuery.prototype{ // ?添加實例屬性和方法

????????jQuery:版本

????????constructor:修正指向問題

????????init():初始化和參數管理

????????selector:存儲選擇字符串

????????length:this對象的長度

????????toArray():this對象的長度

????????get():轉原生集合

????????pushStack():JQ對象的入棧

????????each():遍歷集合

????????ready():DOM加載的接口

????????slice():集合的截取

????????first():集合的第一項

????????last():集合的最后一項

????????eq():集合的指定項

????????map():返回集合前一個狀態

????????push():(內部使用)

????????sort():(內部使用)

????????splice():(內部使用)

}

</script>

這里面的方法都在后面加上了括號,

屬性是不加括號的,

這些方法和屬性大家看著有點比較眼熟吧,

那咱們也一個一個分析,從第一個看起,

先看一下這個版本,版本這個屬性是什么?

????jquery: core_version,

其實版本就是指向這個變量,

這個變量咱們前面看見過,

core_version= "2.0.3",

就是這個字符串,

所以咱們可以找到這個版本這個屬性,

版本這個屬性可能會在后面的代碼上用到,

所以咱們先了解了解這個,

咱們來找一下這一個屬性,

<!-- 咱們先引入jQuery庫 -->

<script src="./jquery-2.0.3.js"></script>

<script>

????// 很簡單,我們想創建一個jQuery對象

????// 然后再來找一下這一個屬性,看一下現在的版本是多少

????????alert($().jquery);

</script>

彈出的結果如下:

這時的版本就是這個2.0.3這個版本。

OK,咱們在往下,看下面的這塊,

constructor:修正指向問題

咱們來看下源碼,就是這句話,

constructor: jQuery,

如果了解面向對象的小伙伴,

應該知道constructor是什么,

constructor在面向對象當中,

創建出來的對象所擁有的一個屬性,

這個屬性就指向這個對象所屬的構造函數,

比如我們來簡單的來寫一寫,

// 假如我在這里寫一個構造函數

????function Aaa(){


}

// 然后我們來創建一個對象

????var a1 = new Aaa();

// a1下邊就會自動生成constructor這個屬性

????alert(a1.constructor);

彈出來的結果如下:

可以發現這個屬性彈出來的就是這個對象對應的構造函數,

所以說當寫完這個函數之后,這個屬性就已經生成了,

JS源碼當中,不是jQuery源碼哈,

// 當一個函數創建完成后,就會在原型下添加constructor屬性

// 指向的就是這個構造函數

Aaa.prototype.constructor = Aaa;

這句話是JS源碼當中自動生成的,

所以當我們調用的時候是可以找到它的,

既然是自動生成的,

為什么jQuery還要手動地去指向一下呢?

原因是因為它這種寫法是把指向改了,

咱們來看一下啊,

function Aaa(){


}

// 比如說我們現在不指向Aaa,指向數組

????Aaa.prototype.constructor = Array;

????var a1 = new Aaa();

????alert(a1.constructor);

這樣的話一彈出結果,

發沒發現就跑到這個數組上面去了,

所以constructor這個屬性非常容易會

被我們不經意之間就修改掉了,

所以說有些特殊情況需要修復一下,

比如,什么樣的特殊情況,我們來看下,

????function Aaa(){


}

// 比如我們給原型下添加兩個屬性

????Aaa.prototype.name = 'Hello';

????Aaa.prototype.age = 20;

????var a1 = new Aaa();

????alert(a1.constructor);

現在這樣寫完之后這是沒有任何問題的,

而且我們知道原型本身就是對象,

既然它是對象,我們也可以改成簡寫方式,

Aaa.prototype = {

????????name:'Hello',

????????age:20

}

這兩種寫法其實是一樣的,

在大部分的情況下都是沒有區別的,

但是在面向對象當中呢,

這兩種寫法是有區別的,

我們先來看一下上邊的寫法,

彈出來的結果如下,沒有任何問題,

接下來,我們看下面這種寫法,

彈出的結果如下:

發沒發現這個并不是Aaa了,

而是object這個對象構造函數,

這個是怎么回事呢?

上面這種寫法這個nameage

都是往原型上添加處理,

所以說默認添加,

這句話是不會受到任何影響的,

但是,下面這一種就不一樣了,

這種寫法不是添加,

而是對這個原型進行覆蓋,

所以這時的constructor

肯定是指向覆蓋它的這個對象所對應的構造函數,

所以說指向就出現問題了,

既然指向出了問題了,我們平時用的時候,

還需要將它的這個指向修正過來,

要不然后期用的時候,

肯定是會找不到或出問題的,

所以說經常我們會去修正它,

就是讓它指向正確給它修正一下,

Aaa.prototype = {

????????constructor:Aaa,

????????name:'Hello',

????????age:20

}

修正完了,再來看一下結果,

修正完了后是不是就正確了,

這時大家就知道了jQuery源碼

為什么會寫這一句話,

這就是解決這句話的一個原因,

下邊我們來看一下init這個方法,

init():初始化和參數管理

前面我們都知道在對外提供接口的時候,

是不是只有 $jQuery 這兩個,

$();

jQuery();

?$ 就是jQuery的簡寫方式,

其實它們倆就是同一個函數,

最終都調到哪個函數?

前面我們也說過就是下面這個,

// 第60行開始

// 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 );

????},

調到這個接口之后,

里面真正的構造函數,

其實是這個init

所以說對外接口兩個參數傳過來的時候,

一個是元素,另一個是作用域,

這兩個傳過來之后,

它們都傳到了init當中了,

還是在init當中進行處理的,

而第三個參數是沒有提供給我們的,

只是它內部寫的一個根節點,

其實在jQuery當中可以接收的類型非常之多,

這個init會對這些類型簡單的分配,

然后再分別的進行處理,

// 107行

// HANDLE: $(""), $(null), $(undefined), $(false)

????????if ( !selector ) {

????????????return this;

????????}

這一塊就是對注釋的進行處理,

其實當我們有的時候寫一些不正確的選擇元素的時候,

然后它去判斷了字符串,

// 109行

// 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 );

????????????}

既然是判斷字符串的話,

那么說明,$選擇的有idclass、標簽,

或者一些更復雜的,

是不是這些都是字符串啊,

????$('#box1');

????$('.box2');

????$('div');

????$('#div div.box');

除了這種選擇字符串的方法,

還有類似于如下的,

????$('<li>');

咱們都知道這樣寫是創建一個li標簽,

所以字符串不僅可以選擇,還可以創建,

所以說這個字符串的類型也比較多,

比如還有一些稍微復雜一點的創建,

$('<li>1</li><li>2</li>');

其實都是走的這個字符串判斷,

接下來它是對哪里進行處理的呢?

// 176行 ??

// HANDLE: $(DOMElement)

????????} else if ( selector.nodeType ) {

????????????this.context = this[0] = selector;

????????????this.length = 1;

????????????return this;

這一塊的對DOM元素進行處理的,

// 比如選擇的this

????$(this);

// 或者document

????$(document);

就會走這里。

接著往后,比如說下面這一塊,

// HANDLE: $(function)

????????// Shortcut for document ready

????????} else if ( jQuery.isFunction( selector ) ) {

????????????return rootjQuery.ready( selector );

????????}

這一塊處理的是 $ 傳函數的形式,

// 比如說加個函數 ?

// 咱們平時用它做文檔加載

// 所以傳函數的形式該怎么處理

????$(function(){


})

好,就是這樣一個順序,

下邊就是下面這一塊了,

return jQuery.makeArray( selector, this );

這一塊就比較簡單,

它處理的是數組和對象的形式。

所以我們簡單把init框架寫一下,

$(' '),$(null),$(undefined),$(false)

$('#div1'),$('.box'),$('div'),$('#div div.box')

$('<li>'),$('<li>1</li><li>2</li>')

第一塊其實很簡單,

就是當你寫錯的時候,

無非就是走if了,

讓它直接返回,

就不讓它繼續往下執行了,

這個其實很簡單,

程序也不會說有問題會報錯啊,

或者是影響到下邊的運行啊,

return 對象是很正常的,

這個對象就會在外面生成的。


OK,這一節咱先講到這里




回看上一集:

原文中此處為鏈接,暫不支持采集


別走開,下集更精彩。

喜歡文章的小伙伴,

希望大家多多轉發分享,

你的分享就是我的動力!


喜歡 分享


or

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,401評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,069評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,635評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,128評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,365評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,881評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,733評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,935評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,172評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,595評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,908評論 2 372

推薦閱讀更多精彩內容