国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 語(yǔ)言 > JavaScript > 正文

jQuery選擇器源碼解讀(二):select方法

2024-05-06 16:17:52
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

這篇文章主要介紹了jQuery選擇器源碼解讀(二):select方法,本文用詳細(xì)的注釋解讀了select方法的實(shí)現(xiàn)源碼,需要的朋友可以參考下

 

 
  1. /* 
  2. * select方法是Sizzle選擇器包的核心方法之一,其主要完成下列任務(wù): 
  3. * 1、調(diào)用tokenize方法完成對(duì)選擇器的解析 
  4. * 2、對(duì)于沒有初始集合(即seed沒有賦值)且是單一塊選擇器(即選擇器字符串中沒有逗號(hào)), 
  5. * 完成下列事項(xiàng): 
  6. * 1) 對(duì)于首選擇器是ID類型且context是document的,則直接獲取對(duì)象替代傳入的context對(duì)象 
  7. * 2) 若選擇器是單一選擇器,且是id、class、tag類型的,則直接獲取并返回匹配的DOM元素 
  8. * 3) 獲取最后一個(gè)id、class、tag類型選擇器的匹配DOM元素賦值給初始集合(即seed變量) 
  9. * 3、通過調(diào)用compile方法獲取“預(yù)編譯”代碼并執(zhí)行,獲取并返回匹配的DOM元素 
  10.  
  11. * @param selector 已去掉頭尾空白的選擇器字符串 
  12. * @param context 執(zhí)行匹配的最初的上下文(即DOM元素集合)。若context沒有賦值,則取document。 
  13. * @param results 已匹配出的部分最終結(jié)果。若results沒有賦值,則賦予空數(shù)組。 
  14. * @param seed 初始集合 
  15. */ 
  16. function select(selector, context, results, seed) { 
  17.  
  18. var i, tokens, token, type, find,  
  19. // 調(diào)用tokenize函數(shù)解析selector 
  20. match = tokenize(selector); 
  21.  
  22. // 若沒有提供初始集合 
  23. if (!seed) { 
  24. // Try to minimize operations if there is only one group 
  25. // 若只有一組選擇器,即選擇器字符串沒有逗號(hào) 
  26. if (match.length === 1) { 
  27. // Take a shortcut and set the context if the root selector 
  28. // is an ID 
  29. /* 
  30. * 下面代碼是用來(lái)處理根選擇器是ID類型的快捷方式 
  31.  
  32. * 在此使用slice[0]來(lái)創(chuàng)建一個(gè)新的集合, 
  33. * 確保原有的集合不會(huì)被之后代碼變更掉 
  34. */ 
  35. tokens = match[0] = match[0].slice(0); 
  36. /* 
  37. * 若選擇器是以id類型開始,且第二個(gè)是關(guān)系符(即+~>或空格), 
  38. * 則獲取id所屬對(duì)象作為context繼續(xù)完成后續(xù)的匹配 
  39.  
  40. * 此處的條件判斷依次為: 
  41. * tokens.length > 2 :若tokens有兩個(gè)以上的選擇器 
  42. * (token = tokens[0]).type === "ID" :第一個(gè)選擇器的類型為ID(即以#開頭的), 
  43. * support.getById :支持getElementById函數(shù) 
  44. * context.nodeType === 9 :context對(duì)象是document 
  45. * documentIsHTML :當(dāng)前處理的是HTML代碼 
  46. * Expr.relative[tokens[1].type] :第二個(gè)tokens元素是一個(gè)關(guān)系(即+~>或空格) 
  47. * 在滿足上面所有條件的情況下,執(zhí)行if內(nèi)的語(yǔ)句體 
  48. */ 
  49. if (tokens.length > 2 && (token = tokens[0]).type === "ID" 
  50. && support.getById && context.nodeType === 9 
  51. && documentIsHTML && Expr.relative[tokens[1].type]) { 
  52.  
  53. // 將當(dāng)前上下文指向第一個(gè)ID選擇器指定的節(jié)點(diǎn)對(duì)象 
  54. context = (Expr.find["ID"](token.matches[0].replace( 
  55. runescape, funescape), context) || [])[0]; 
  56.  
  57. // 若當(dāng)前上下文內(nèi)沒有指定ID對(duì)象,則直接返回results 
  58. if (!context) { 
  59. return results; 
  60.  
  61. // 選擇器字符串去掉第一個(gè)ID選擇器 
  62. selector = selector.slice(tokens.shift().value.length); 
  63.  
  64. // Fetch a seed set for right-to-left matching 
  65. /*  
  66. * 下面while循環(huán)的作用是用來(lái)根據(jù)最后一個(gè)id、class、tag類型的選擇器獲取初始集合 
  67. * 舉個(gè)簡(jiǎn)單例子:若選擇器是"div[title='2']", 
  68. * 代碼根據(jù)div獲取出所有的context下的div節(jié)點(diǎn),并把這個(gè)集合賦給seed變量, 
  69. * 然后在調(diào)用compile函數(shù),產(chǎn)生預(yù)編譯代碼, 
  70. * 預(yù)編譯代碼完成在上述初始集合中執(zhí)行[title='2']的匹配 
  71.  
  72. * 首先,檢查選擇器字符串中是否存在與needsContext正則表達(dá)式相匹配的字符 
  73. * 若沒有,則將依據(jù)選擇器從右到左過濾DOM節(jié)點(diǎn) 
  74. * 否則,將先生成預(yù)編譯代碼后執(zhí)行(調(diào)用compile方法)。  
  75. */ 
  76.  
  77. /* 
  78. * "needsContext" : new RegExp("^" + whitespace 
  79. * + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?://(" 
  80. * + whitespace + "*((?:-//d)?//d*)" + whitespace 
  81. * + "*//)|)(?=[^-]|$)", "i") 
  82. * needsContext用來(lái)匹配選擇器字符串中是否包含下列內(nèi)容: 
  83. * 1、>+~三種關(guān)系符 
  84. * 2、:even、:odd、:eq、:gt、:lt、:nth、:first、:last八種偽類 
  85. * 其中,(?=[^-]|$)用來(lái)過濾掉類似于:first-child等帶中杠的且以上述八個(gè)單詞開頭的其它選擇器 
  86. */ 
  87. i = matchExpr["needsContext"].test(selector) ? 0 
  88. : tokens.length; 
  89. while (i--) { 
  90. token = tokens[i]; 
  91.  
  92. // Abort if we hit a combinator 
  93. // 遇到關(guān)系符跳出循環(huán) 
  94. if (Expr.relative[(type = token.type)]) { 
  95. break
  96. if ((find = Expr.find[type])) { 
  97. // Search, expanding context for leading sibling 
  98. // combinators 
  99. /* 
  100. * rsibling = new RegExp(whitespace + "*[+~]") 
  101. * rsibling用于判定token選擇器是否是兄弟關(guān)系符 
  102. */ 
  103. if ((seed = find(token.matches[0].replace( 
  104. runescape, funescape), rsibling 
  105. .test(tokens[0].type) 
  106. && context.parentNode || context))) { 
  107.  
  108. // If seed is empty or no tokens remain, we can 
  109. // return early 
  110. // 剔除剛用過的選擇器 
  111. tokens.splice(i, 1); 
  112. selector = seed.length && toSelector(tokens); 
  113. /* 
  114. * 若selector為空,說明選擇器僅為單一id、class、tag類型的, 
  115. * 故直接返回獲取的結(jié)果,否則,在獲取seed的基礎(chǔ)上繼續(xù)匹配 
  116. */ 
  117. if (!selector) { 
  118. push.apply(results, seed); 
  119. return results; 
  120.  
  121. break
  122.  
  123. // Compile and execute a filtering function 
  124. // Provide `match` to avoid retokenization if we modified the 
  125. // selector above 
  126. /* 
  127. * 先執(zhí)行compile(selector, match),它會(huì)返回一個(gè)“預(yù)編譯”函數(shù), 
  128. * 然后調(diào)用該函數(shù)獲取最后匹配結(jié)果 
  129. */ 
  130. compile(selector, match)(seed, context, !documentIsHTML, results, 
  131. rsibling.test(selector)); 
  132. return results; 

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 雷州市| 城步| 抚州市| 吉林市| 新巴尔虎左旗| 柳州市| 岳阳县| 安达市| 兴业县| 寻甸| 宿迁市| 临邑县| 汝州市| 商河县| 开鲁县| 汽车| 西充县| 岳阳县| 元谋县| 彭州市| 诸城市| 加查县| 闽侯县| 广元市| 延庆县| 新建县| 桐梓县| 甘孜县| 泸定县| 新邵县| 周宁县| 永嘉县| 阿拉善右旗| 偏关县| 乐平市| 吉首市| 石家庄市| 建水县| 博客| 杭锦旗| 调兵山市|