亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

jQuery選擇器源碼解讀(三):tokenize方法

2019-11-20 12:49:34
字體:
來源:轉載
供稿:網友
/* * tokenize方法是選擇器解析的核心函數,它將選擇器轉換成兩級數組groups * 舉例: *  若選擇器為“div.class,span”,則解析后的結果為: *  group[0][0] = {type:'TAG',value:'div',matches:match} *  group[0][1] = {type:'CLASS',value:'.class',matches:match} *  group[1][0] = {type:'TAG',value:'span',matches:match} * 由上述結果可以看出,groups的每一個元素以逗號分隔的選擇器塊的解析結果, * 另外,上述結果中的matches等于模式匹配的結果,由于在此不方便寫清楚, * 故只把代碼matches:match寫在這里。 *  * tokenize方法完成如下兩個主要任務: * 1、解析選擇器 * 2、將解析結果存入緩存中,以備后用 *  *  * @param selector 待解析的選擇器字符串 * @param parseOnly 為true時,說明本次調用是匹配子選擇器 *  舉個例子:若初始選擇器為"div:not(.class:not(:eq(4))):eq(3)" *  代碼首先匹配出TAG選擇器div, *  之后匹配出的pseudo選擇器字符串是:not(.class:not(:eq(4))):eq(3), *  代碼會把“.class:not(:eq(4))):eq(3”作為not的括號內的值進一步進行解析, *  此時代碼在調用tokenize解析時,parseOnly參數會傳入true. */function tokenize(selector, parseOnly) {	var matched, match, tokens, type, soFar, groups, preFilters, 	// 獲取緩存中的結果	cached = tokenCache[selector + " "];	/*	 * 若緩存中有selector對應的解析結果	 * 則執行if中語句體	 */	if (cached) {		// 若是對初始選擇器解析(parseOnly!=true),則返回緩存結果,		// 若不是,則返回0		return parseOnly ? 0 : cached.slice(0);	}	/*	 * 由于字符串在javascript中不是作為對象來處理的,	 * 所以通過賦值,代碼就自動復制了一個新字符串給了soFar,	 * 這樣,對soFar的任何處理都不會影響selector的原有數據	 */	soFar = selector;	groups = [];	// 此處賦值,僅僅用于減少后續代碼字數,縮短執行路徑	preFilters = Expr.preFilter;	while (soFar) {		// Comma and first run		/*		 * rcomma = new RegExp("^" + whitespace + "*," + whitespace + "*")		 * rcomma用來判定是否存在多個選擇器塊,即用逗號隔開的多個并列的選擇器		 * 		 * 下面條件判定依次為:		 * !matched:若是第一次執行循環體,則為true;否則為false。		 *   這里matched即作為是否第一次執行循環體的標識,		 *   也作為本次循環中soFar是否以非法字符串(即非合法單一選擇器)開頭的標志。		 * (match = rcomma.exec(soFar):獲取符合rcomma的匹配項		 */		if (!matched || (match = rcomma.exec(soFar))) {			if (match) {				// Don't consume trailing commas as valid				/*				 * 剔除掉第一個逗號及之前的所有字符				 * 舉個例子:				 * 若初始選擇器為:"div.news,span.closed",				 * 在解析過程中,首先由后續代碼解析完畢div.news,剩下",span.closed"				 * 在循環體內執行到這里時,將逗號及之前之后連續的空白(match[0])刪除掉,				 * 使soFar變成"span.closed",繼續執行解析過程				 * 				 * 在這里,若初始選擇器的最后一個非空白字符是逗號,				 * 那么執行下面代碼時soFar不變,即soFar.slice(match[0].length)返回空字符串,				 * 故最終返回的是||后面的soFar				 */				soFar = soFar.slice(match[0].length) || soFar;			}						/*			 * 在第一次執行循環體或者遇到逗號分割符時,將tokens賦值為一個空數組,			 * 同時壓入groups數組			 */			groups.push(tokens = []);		}		matched = false;		// Combinators		/*		 * rcombinators = new RegExp(		 *		"^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*"),		 * rcombinators用來匹配四種關系符,即>+~和空白		 * 		 * 若soFar中是以關系符開始的,則執行if內的語句體		 */		if ((match = rcombinators.exec(soFar))) {			/*			 * 將match[0]移除match數組,同時將它賦予matched			 * 若原本關系符兩邊帶有空格,則此時match[0]與matched是不相等的			 * 舉個例子:			 * 若soFar = " + .div";			 * 執行match = rcombinators.exec(soFar)后,			 * match[0] = " + ",而match[1]="+";			 * 執行完matched = match.shift()后,			 * matched=" + ",而match[0]="+";			 */			matched = match.shift();			// 將匹配結果壓入tokens數組中			tokens.push({				value : matched,				// Cast descendant combinators to space				/*				 * rtrim = new RegExp("^" + whitespace + "+|((?:^|[^////])(?:////.)*)"				 *			+ whitespace + "+$", "g"),				 * whitespace = "[//x20//t//r//n//f]";				 * 				 * 下面match[0].replace(rtrim, " ")的作用是將match[0]左右兩邊的空白替換為空格				 * 但是由于其上的match.shift的作用,match[0]已經是兩邊不帶空白的字符串了,				 * 故此出的替換是沒有用途的代碼				 */				type : match[0].replace(rtrim, " ")			});						// 將關系符之后的字符串賦予soFar,繼續解析			soFar = soFar.slice(matched.length);		}		// Filters		/*		 * 下面通過for語句對soFar逐一匹配ID、TAG、CLASS、CHILD、ATTR、PSEUDO類型的選擇器		 * 若匹配到了,則先調用該類型選擇器對應的預過濾函數,		 * 然后,將結果壓入tokens數組,繼續本次循環。		 */		for (type in Expr.filter) {			/*			 * match = matchExpr[type].exec(soFar):對soFar調用type類型的正則表達式對soFar進行匹配,			 *  并將匹配結果賦予match。若未匹配到數據,則match為undefined。			 * !preFilters[type]:若不存在type類型的預過濾函數,則為true			 * match = preFilters[type](match):執行預過濾,并將結果返回給match			 * 			 */			if ((match = matchExpr[type].exec(soFar))					&& (!preFilters[type] || (match = preFilters[type]							(match)))) {				// 將match[0]移除match數組,同時將它賦予matched				matched = match.shift();				// 將匹配結果壓入tokens數組中				tokens.push({					value : matched,					type : type,					matches : match				});				// 將匹配結果之后的字符串賦予soFar,繼續解析				soFar = soFar.slice(matched.length);			}		}		/*		 * 若matched==false,		 * 則說明本次循環沒有有效的選擇器(包括關系符和id、class等類型選擇器)		 * 因此,解析到當前位置遺留下來的soFar是非法的選擇器字符串		 * 跳出while循環體		 */		if (!matched) {			break;		}	}	// Return the length of the invalid excess	// if we're just parsing	// Otherwise, throw an error or return tokens	/*	 * 若不是對初始選擇器字符串進行解析(!parseOnly==true),	 *  則返回soFar.length,此時的soFar.length代表連續有效的選擇器最終位置,	 *  后續文章將以實例進行說明	 * 若是對初始選擇器字符串進行解析,則看soFar是否還有字符,	 *  若是,則執行Sizzle.error(selector)拋出異常;	 *  若不是,則執行tokenCache(selector, groups).slice(0)將結果壓入緩存,并返回結果的副本。	 */	return parseOnly ? soFar.length : soFar ? Sizzle.error(selector) :	// Cache the tokens	tokenCache(selector, groups).slice(0);}

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产欧美一区二区三区视频| 欧美高清无遮挡| 欧美贵妇videos办公室| 国产日韩欧美日韩大片| 免费91麻豆精品国产自产在线观看| 国产精品成人av在线| 日韩av手机在线| 国产精品久久久久久久久久久久久久| 美日韩精品免费观看视频| 中文字幕日韩视频| 国产精品一区二区三| 性色av一区二区三区免费| 国产免费一区二区三区在线观看| 欧美在线观看一区二区三区| 国产伦精品免费视频| 日韩福利视频在线观看| 日本精品视频在线观看| 亚洲成**性毛茸茸| 亚洲无线码在线一区观看| 欧美在线亚洲在线| 久久97精品久久久久久久不卡| 丝袜美腿精品国产二区| 91久久精品国产91久久性色| 国产自摸综合网| 国产精品a久久久久久| 欧美精品videos另类日本| 国产综合久久久久| 久久人人爽人人爽人人片av高清| 久久手机精品视频| 欧美性猛交xxxx| 日韩三级影视基地| 国产精品久久久久9999| 日韩在线视频国产| 亚洲美女精品成人在线视频| 精品中文字幕在线| 欧美成人午夜剧场免费观看| 亚洲欧洲一区二区三区久久| 久久久午夜视频| 久久久精品视频在线观看| 国模精品一区二区三区色天香| 亚洲男人天堂手机在线| 日本一区二三区好的精华液| 日韩精品免费视频| 中文字幕亚洲图片| 国产日韩中文字幕在线| 精品视频久久久久久久| 国产成人av网址| 欧美激情亚洲另类| 4k岛国日韩精品**专区| 91免费福利视频| 久久精品精品电影网| 4438全国成人免费| 91av在线播放| 岛国av一区二区在线在线观看| 伦伦影院午夜日韩欧美限制| 欧美大全免费观看电视剧大泉洋| 亚洲va久久久噜噜噜久久天堂| 久久久亚洲国产天美传媒修理工| 麻豆乱码国产一区二区三区| 亚洲激情免费观看| 亚洲精品第一页| 国外视频精品毛片| 久久青草福利网站| 亚洲欧洲在线视频| 日韩精品在线观看视频| 亚洲精品aⅴ中文字幕乱码| 欧美又大又粗又长| 亚洲欧美日韩直播| 性欧美长视频免费观看不卡| 91av在线不卡| 亚洲精品免费网站| 国a精品视频大全| 久久精品91久久久久久再现| 色悠悠久久88| 热re91久久精品国99热蜜臀| 中文字幕在线亚洲| 亚洲视频网站在线观看| 国产成人高潮免费观看精品| 欧美大片va欧美在线播放| 国产最新精品视频| 国产精品极品尤物在线观看| 狠狠色香婷婷久久亚洲精品| 欧美一级淫片播放口| 欧美激情第三页| 国产精品成人v| 日韩一区在线视频| 日韩精品日韩在线观看| 久久久久久久久久久免费| 亚洲国产精品成人va在线观看| 国产美女久久精品香蕉69| 国产自产女人91一区在线观看| 视频在线一区二区| www亚洲精品| 91成品人片a无限观看| 久久精品一本久久99精品| 欧洲亚洲女同hd| 午夜精品视频在线| 欧美日本高清一区| 日韩精品视频在线观看网址| 在线观看91久久久久久| 欧美激情视频在线观看| 久久久噜噜噜久久| 亚洲精品网站在线播放gif| 亚洲精品av在线播放| 一本色道久久综合狠狠躁篇怎么玩| 尤物99国产成人精品视频| 欧美成人激情在线| 日韩性生活视频| 欧洲永久精品大片ww免费漫画| 成人动漫网站在线观看| 久久久91精品国产一区不卡| 亚洲成人动漫在线播放| 欧美日韩视频在线| 亚洲成人激情在线观看| 久久久视频免费观看| 亚洲第一精品夜夜躁人人躁| 国产精品影院在线观看| 中文字幕亚洲一区二区三区| 日韩风俗一区 二区| 国产精品视频免费观看www| 国产精品一区二区久久久久| 亚洲国产精品嫩草影院久久| 日韩欧美aⅴ综合网站发布| 日本精品免费一区二区三区| 日韩av手机在线| 亚洲视频在线免费观看| 欧美激情2020午夜免费观看| 国产精品678| 欧美日韩国产色| www.精品av.com| 91理论片午午论夜理片久久| 91久久国产精品91久久性色| 日韩av电影手机在线| 这里只有精品在线播放| 国产精品主播视频| 午夜精品视频网站| 亚洲人成在线观看网站高清| 欧美激情综合色综合啪啪五月| 国产视频精品va久久久久久| 福利二区91精品bt7086| 最近的2019中文字幕免费一页| 亚洲精品国产精品国产自| 欧美国产激情18| 国产精品视频xxx| 亚洲一区二区三区sesese| 亚洲第一av网| 91av成人在线| 欧美亚洲国产成人精品| 永久免费毛片在线播放不卡| 久久国产精品亚洲| 亚洲精品永久免费精品| 日韩免费不卡av| 国产精品福利在线观看| 日韩av一区二区在线观看| 欧美日韩高清区| 日韩中文字幕视频在线观看| 伊人成人开心激情综合网| 久久在线精品视频| 日韩一区二区av| 久久手机免费视频| 亚洲色无码播放| 亚洲伊人久久大香线蕉av| 日韩视频永久免费观看| 久久精品一偷一偷国产|