jquery index()方法源碼解析

平時(shí)工作中,相信很多小伙伴跟我一樣,jquery的index()方法用的很多,也用得很爽,一直都覺得不可思議。今天就偶然想了解一下它的實(shí)現(xiàn)原理,便翻起了jquery的源碼,窺得了它大致的實(shí)現(xiàn)原理。

場(chǎng)景重現(xiàn):(jquery自行引入)

html:

<ul id="test">
    <li id="t1">1</li>
    <li id="t2">2</li>
    <li id="t3">3</li>
</ul>

js:

$("#test").on('click', 'li', function(e) {
    console.log($(this).index());
})

就如此小的一個(gè)demo,引發(fā)了我對(duì)index()方法的種種聯(lián)想,為什么點(diǎn)擊當(dāng)前的元素可以知道它的索引呢?難道要預(yù)先知道它的父級(jí)嗎,這不可能,這些dom節(jié)點(diǎn)又不是固定的,那到底。。。。。。

下面就開啟源碼之旅吧。

首先是index()方法,其源碼如下:

index: function( elem ) {
    // No argument, return index in parent
    if ( !elem ) {
        return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
    }
    // Index in selector
    if ( typeof elem === "string" ) {
        return indexOf.call( jQuery( elem ), this[ 0 ] );
    }
    // Locate the position of the desired element
    return indexOf.call( this,
        // If it receives a jQuery object, the first element is used
        elem.jquery ? elem[ 0 ] : elem
    );
}

源碼很精簡(jiǎn),而且我們只想看沒傳參時(shí)的index方法的用法,所以只看這句:

if ( !elem ) {
    return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
}

其實(shí)這句的重點(diǎn)在prevAll方法,其它都是些使邏輯嚴(yán)謹(jǐn)?shù)拇a,因此我們側(cè)重點(diǎn)放在prevAll方法。所以,翻看了prevAll方法:

jQuery.each({
    // ...此處省略了很多非相關(guān)代碼
    prevAll: function( elem ) {
      return dir( elem, "previousSibling" );
    },
}, function(name, fn) { // ...省略 })

緊接著,我們看dir源碼:

function dir( elem, dir, until ) {
    var matched = [],
        truncate = until !== undefined;

    while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
        if ( elem.nodeType === 1 ) {
            if ( truncate && jQuery( elem ).is( until ) ) {
                break;
            }
            matched.push( elem );
        }
    }
    return matched;
}

看到這里,其實(shí)大致思路已經(jīng)知道了:遍歷查找當(dāng)前元素的上一個(gè)同級(jí)元素,形成一個(gè)包含所有該元素的前面的元素的集合。可能有點(diǎn)拗口,回到我們的小demo,在控制臺(tái)模擬一下prevAll的過(guò)程,看著以下截圖應(yīng)該好理解些:


控制臺(tái)模擬

而dir函數(shù)已經(jīng)為我們過(guò)濾了文本節(jié)點(diǎn):

if ( elem.nodeType === 1 )

最終就是返回一個(gè)所有的前面元素的集合給我們了,然后index就是prevAll().length(該集合的長(zhǎng)度)了。

ps: 可能細(xì)心的小伙伴會(huì)發(fā)現(xiàn)有漏洞,index源碼上是這樣的:

if ( !elem ) {
    return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
}

人家的prevAll明明沒傳參數(shù),那按道理prevAll就接收不到elem參數(shù),則elem為undefined,那就沒有后續(xù)的故事情節(jié)了。關(guān)于這個(gè),我只想說(shuō),你知道得太多了。。。。。。


xx

由于本人精力有限,所以只能猜想是jQuery.each方法做了手腳,使得不傳參的prevAll里面的elem自動(dòng)變?yōu)閠his對(duì)象。(當(dāng)然這只是本人猜想),希望有知道的留言一下,共勉,謝謝大家。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容