jQuery原型方法first,last,eq,slice源碼分析

這4個方法中前3個方法很經常使用你們都見過,可是slice方法可能會覺得是數組方法,其實slice也是jQuery的一個原型方法,只不過是底層方法是爲其餘方法服務的(更具體點是爲eq方法服務的),首先仍是看下這幾個方法前臺是怎麼使用的;html

eq 概述  獲取第N個元素

參數

一個整數,指示元素的位置,從集合中的最後一個元素開始倒數。(1算起)數組

示例

參數index描述:

//獲取匹配的第二個元素

//HTML 代碼:

<p> This is just a test.</p> <p> So is this</p>
//jQuery 代碼:
 $("p").eq(1) //結果:
 [ <p> So is this</p> ]

參數-index描述:

//獲取匹配的第二個元素

//HTML 代碼:

<p> This is just a test.</p> <p> So is this</p>
//jQuery 代碼:
 $("p").eq(-2) //結果:
 [ <p> This is just a test.</p> ]

first()   獲取第一個元素

示例

描述:

獲取匹配的第一個元素app

//HTML 代碼:

<ul>
    <li>list item 1</li>
    <li>list item 2</li>
    <li>list item 3</li>
    <li>list item 4</li>
    <li>list item 5</li>
</ul>
//jQuery 代碼:
 $('li').first() //結果:
 [ <li>list item 1</li> ]

last()  獲取最後個元素

示例

描述:

獲取匹配的最後個元素dom

//HTML 代碼:

<ul>
    <li>list item 1</li>
    <li>list item 2</li>
    <li>list item 3</li>
    <li>list item 4</li>
    <li>list item 5</li>
</ul>
//jQuery 代碼:
 $('li').last() //結果:
 [ <li>list item 5</li> ]

 

下面來看1.7.1中的源碼:this

eq: function( i ) { i = +i; return i === -1 ?
            this.slice( i ) : this.slice( i, i + 1 ); }, first: function() { return this.eq( 0 ); }, last: function() { return this.eq( -1 ); }, slice: function() { return this.pushStack( slice.apply( this, arguments ), "slice", slice.call(arguments).join(",") ); },

東西其實很少並且都是相互引用,首先咱們能夠簡單的分下他們的關係  first,last>eq>slice>pushStack;spa

因此最紅結果的輸出依賴pushStack方法,此方法介紹在上一篇隨筆中http://www.cnblogs.com/yy-hh/p/4636106.html感興趣的能夠了解下或者參考源碼;因此直接從slice方法開始;調試

在源碼中能夠看到是直接ruturn pushStack處理後的結果,而在pushStack方法中須要3個參數,第一個是待處理元素數組,第二個是調用的方法,第三個是傳入的selector,其中真正做用的是第一個參數剩下的兩個參數是做調試使用的,他最後會返回一個新的jQuery對象,而且會在這個對象中添加一個prevObject屬性執行原來的或者叫執行此方法時的jQuery對象,具體的請參考介紹pushStack的隨筆。下面重點來看下參數的處理:code

slice.apply( this, arguments )

這個是一個數組的截取,實際上是一個類數組或者特殊數組轉換爲純數組的方法,前面咱們介紹的toArray方法亦是如此htm

toArray: function() { return slice.call( this, 0 ); },

這不過是這裏並非須要全部的元素而是僅僅保留數字下標的dom元素,爲了更方便的理解咱們在前臺調用下這個方法而後觀察源碼中的結果變化:對象

    <script> $('div').slice(); </script>
slice: function() { console.log(this); console.log(this.toArray()); console.log(slice.apply( this, arguments)); return this.pushStack( slice.apply( this, arguments ), "slice", slice.call(arguments).join(",") ); }, //Object { 0: <div>, 1: <div>, length: 2, prevObject: Object, context: HTMLDocument → test.html, selector: "div" }  //Array [ <div>, <div> ]  //Array [ <div>, <div> ]

結果是否是很明顯呢?在未處理以前是一個jQuery對象,擁有衆多屬性和方法在使用toArray方法和slice.apply( this, arguments)結果是同樣的僅僅保留的是兩個dom元素,不是全部的非數組都是能夠這樣轉化的必定要是從0開始下標並且有length屬性的才能夠或者更簡單點可使用for循環的。可是既然可使用toArray方法直接不就好了幹嗎還要在寫一個用對象冒充一次呢,其實toArray方法只是arguments爲0的特殊狀況,toArray方法也是寫得很清楚,若是我調用此方法加上參數就不同了例如:

 $('div').slice(0,1);
Object { 0: <div>, 1: <div>, length: 2, prevObject: Object, context: HTMLDocument → test.html, selector: "div" } Array [ <div>, <div> ] Array [ <div> ]

第二個參數「slice」就是從這個方法入棧的做爲調試用,第三個參數是一個字符串arguments是類數組因此要對象冒充掉join方法 在上面例子的調用下就是"0,1" 最後來看看下slice方法最終返回的結果

 console.log($('div').slice(0,1));
Object { 0: <div>, length: 1, prevObject: Object, context: HTMLDocument → test.html, selector: "div.slice(0,1)" }

若是不夠清楚能夠看下目錄

console.dir($('div').slice(0,1));

prevObject屬性指向未調用slice(也就是pushStack)方法時的對象  selector屬性告訴咱們是什麼元素調用了什麼方法入棧的以及參數是什麼

理解了slice方法eq方法就很清晰了:

eq: function( i ) { i = +i; return i === -1 ?
            this.slice( i ) : this.slice( i, i + 1 ); },

返回slice的結果,其實我上面局的例子徹底能夠是eq方法調用轉換而來,由於通常狀況下咱們是不會單獨調用slice方法的例如:

$('div').eq(0);

執行完其實就是return this.slice(0,1);

first方法都是eq方法的特殊狀況當值爲0或1的時候,因此也不建議你們使用這個方法,很差聽點叫脫褲子放屁畫蛇添足啊,好聽點就是增長調用開銷啊。

分析完畢:若是您耐心的看完了此篇仍是不知所云可能有如下幾個緣由:

1.js基礎不夠紮實好比slice,apply等方法的使用

2.沒有了解pushStack方法,這個方法是不少jQuery方法的底層支持方法必定要先弄清楚

相關文章
相關標籤/搜索