車大棒淺談jQuery源碼(二)

前言

原本只是一個本身學習jQuery筆記的簡單分享,沒想到得到這麼多人賞識。我本身也是傻呵呵的一臉迷茫,感受到受寵若驚。jquery

不過仍是有人向批判個人文章說,這是基本知識點,徹底跟jQuery源碼沾不上邊。說jQuery博大精深,還要我靜下心來研究, 別淨整些沒用的。弄的我一臉懵逼,WTF?我從頭至尾都沒有說我講的多高端,我連標題都寫的「淺談」。就徹底不能讓我等菜鳥慢慢先從的簡單的入手嗎?
ide

可是有位名爲「萌新」三好童鞋,就作的很是好。「啪」!,反手就是一拖鞋留言砸過來一串代碼。指出說undefined在ES五、ES6標準中只是全局做用域下不能被定義,一旦脫離全局做用域下undefined就可以被定義。函數

undefined狀況補充

因此但願可以像可以像萌新同窗狠狠打臉找知識點錯誤,而不是指出我這個太簡單一類的。這個我原本就是我的學習過程的淺談一下,給菜鳥一點活路嗎!性能

原型prototype

咱們建立的每一個函數都有一個prototype(原型)屬性,這個屬性是一個指針,指向一個對象,而這個對象的用途是包含能夠由特定類型的全部實例共享的屬性和方法。
--《高級程序第三版》-6.23 原型模式學習

這裏我引用了高級程序第三版當中的一段話用來簡單描述原型prototype,可是這個玩意具體有什麼用?
解釋何爲原型以前, ⾸先看下⾯的代碼:優化

//建立一個構造函數
    function Person() {
        this.sayHello = function() {
            console.log('Hello,I am one Dog')
        }
    }

    //建立兩個對象
    var dog1 = new Person(),
        dog2 = new Person();

    //兩個實例對象進行比較
    dog1.sayHello();
    dog2.sayHello();
    console.log("dog1.sayHello === dog2.sayHello的結果是:" + (dog1.sayHello === dog2.sayHello));

控制檯輸出結果:this

這裏dog1,dog2都是構造函數Person的實例,可是兩我的的sayHello方法並不徹底相等。也就是說dog1和dog2分別在本身所屬空間開闢了一塊內存。prototype

夭壽啦!單身狗爲什麼不報團取暖,不是說好一塊兒相親相愛嗎!不是說好一塊兒共享種子,一塊兒開黑嗎?月黑風高秋名山一塊兒開車嗎!3d

因此爲了不本來天天遭受狗糧侵蝕單身汪繼續團結一致,這個時候原型prototype就起到很好的穩定dog羣內團結的做用。指針

//建立一個構造函數
    function Person(){};
    Person.prototype.sayHello = function(){
        console.log("Hello, I am one Dog")
    }
    
    //建立兩個對象
    var dog1 = new Person(),
        dog2 = new Person();
    
    //兩個實例對象進行比較
    dog1.sayHello();
    dog2.sayHello();
    console.log("dog1.sayHello === dog2.sayHello的結果是:"+ (dog1.sayHello === dog2.sayHello));

控制檯輸出結果:

說明此時兩名單身狗又團結一致,資源共享sayHello方法。而不是每一個私自創建一個空間,去存放sayHello方法。

當實例對象須要尋找sayHello方法的時候,就會先去構造函數Person函數當中尋找sayHello方法,而後Person函數方法當中沒有找到,就會去Person的原型當中去找sayHello方法。(同理在JavaScript當中,若是建立多個對象,可是卻只共享一個方法。減小了內存的使用,可以優化性能很多。)

資源共享的單身汪

而jQuery裏面也充斥很多原型prototype,因此看下面jQuery代碼,就會知道相應查找順序了,一樣也能更好的理解後面的代碼。

jQuery無new構造

以前第一章,咱們有講過jquery經過以下代碼來暴露接口:

window.jquery = window.$ = jQuery

舉個栗子:

$("#box")   =  jQuery("#box")

那麼jQuery這個函數開始執行,此時讓咱們打開jQuery源碼,看看jQuery內部是如何實現的。

(function(window, undefined) {
    var
    // ...
    jQuery = function(selector, context) {
        return new jQuery.fn.init(selector, context, rootjQuery);
    },

    jQuery.fn = jQuery.prototype = {
        init: function(selector, context, rootjQuery) {
            // ...
        }
    }
    jQuery.fn.init.prototype = jQuery.fn;

})(window);

估計有童鞋 jQuery.fn.init.prototype = jQuery.fn 這一句都會被卡主,滿臉黑人問號。可是這句真的算是 jQuery 的絕妙之處。理解這幾句很重要,分別解析一下:

來自靈魂抽象派畫師--車大棒
(來自靈魂抽象派畫師-車大棒)

一、首先要明確,使用 $(‘xxx’) 這種實例化方式,其內部調用的是return new jQuery.fn.init(selector, context, rootjQuery) 這一句話,也就是構造實例是交給了 jQuery.fn.init() 方法取完成。

二、將jQuery.fn.init 的 prototype 屬性設置爲jQuery.fn,那麼使用 new jQuery.fn.init() 生成的對象的原型對象就是jQuery.fn ,因此掛載到 jQuery.fn 上面的函數就至關於掛載到 jQuery.fn.init()生成的 jQuery 對象上,全部使用new jQuery.fn.init()生成的對象也可以訪問到 jQuery.fn 上的全部原型方法。

三、也就是實例化方法存在這麼一個關係鏈
jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype ;
new jQuery.fn.init()至關於 new jQuery() ;
jQuery()返回的是 new jQuery.fn.init(),而 var obj = new jQuery(),因此這 2 者是至關的,因此咱們能夠無 new 實例化 jQuery 對象。

-------來自某博客大牛的小結(看到好多博客上面都有,不清楚誰纔是原創)

PS:
本來這裏打算把曬上我用思惟箭頭圖畫出個整個結構以後,就基本上一句話能夠帶過了。可是我看到別人博客上這一段總結很好,因此就直接引用了。固然寫博客的時候,我就料到直接引用可能會有點影響很差。修改一下,而後用本身語言來講,可能會效果好的多。

可是徹底以爲沒有必要, 好東西我以爲就應該直接拿出來分享。事實上我原本的學習jQuery源碼就是吸取各類視頻資源,以及各路大牛博客去學習參考。別人寫的好,寫的詳細這就是無可厚非的。(若是有原話博客主,對我私自引用有意見。留言,我馬上刪或者改。)

jQuery的鏈式調用

早在第一次接觸jQuery的時候,就被它風騷的鏈式調用給吸引了,感受操做真TMD的6到飛起。
例如:$('div').eq(0).show().end().eq(1).hide();

因此但願待會簡單的談及這個知識點以後,我不但願大家來一句:「大神,這波操做666!!」,而是高呼道:「what?這麼簡單!」(PS:大牛們請無視這句話,還有不懂這兩句話差異的也請無視這句話!)

var oneDog = {
        food : function(){
            console.log("今天晚餐是泡麪和一個滷雞蛋!");
            return this;    
        },
        sad : function(){
            console.log("坐地鐵被餵了十幾站的狗糧!");
            return this;
        },
        game : function(){
            console.log("今天DOTA2開黑10連跪");
            return this;
        },
    }
    
    oneDog.food().sad().game();       //沒錯,這樣就是實現了鏈式調用。

而後控制檯就可以依次輸出每一個方法當中的log語句,就是這麼簡單每次調用返回它本身自己就能夠造成一個鏈式調用。(來!開始喊那句話吧!)

看過前面的小demo以後,讓咱們回過頭來看jQuery的源碼是如何實現鏈式調用。
首先第一步,顯示HTML骨架部分:

<div>我是dog1</div>
    <div>我是dog2</div>

接下來就是jQuery代碼

console.log($(''div').eq(0))

這個時候控制檯輸出結果:

以後在eq(0)後面牢牢跟end()結束的時候,而後至關於整個代碼返回給prevObject這個集合了:

//jQuery源碼當中的end函數
end: function() {
        return this.prevObject || this.constructor(null);
    }

總的來講,

一、eq(i) 以後留下prevObject 屬性,這個屬性記錄了操做的 jQuery 對象集合;

二、當咱們在鏈式調用 end() 方法後,內部就返回當前 jQuery 對象的 prevObject 屬性,完成回溯。

三、和前面咱們返回的this的小demo,有殊途同歸之妙。

小結:

今天將的知識點比較少,先是帶你們回顧了prototype知識點,以後淺談了一下jQuery的無new的構造結構,以及鏈式調用的原理。

兩篇博客所講的知識徹底沒有一些知名大牛博客一篇博客講的知識點多,可是哪怕能講懂一個點我也會很欣慰。有句話說的好:
不積跬步,無以致千里;不積小流,無以成江海。

原創文章,文筆有限,才疏學淺,文中如有不正之處,再次再次再次歡迎各位啪啪啪的打臉賜教。(有句話說的好,重要的詞得說三遍。)
我是車大棒,個人目標是星辰與大海!

相關文章
相關標籤/搜索