sizzle源码分析 (1)sizzle架构

时间:2021-08-09 22:47:43
sizzle是jquery的核心,它用来选择匹配的元素,其代码包含在一个匿名函数中,并以window作为其上下文环境:
(function( window, undefined ) {
//此处为sizzle代码
})( window );
匿名函数体内,首先申明了很多变量,比如下边这些正则表达式:
classCache = createCache(),
/*classCache:
function cache( key, value ) {
// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
if ( keys.push( key += " " ) > Expr.cacheLength ) {
// Only keep the most recent entries
delete cache[ keys.shift() ];
}
return (cache[ key ] = value);
}
*/
tokenCache = createCache(),
/*tokenCache:
function cache( key, value ) {
// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
if ( keys.push( key += " " ) > Expr.cacheLength ) {
// Only keep the most recent entries
delete cache[ keys.shift() ];
}
return (cache[ key ] = value);
}
*/
compilerCache = createCache(),
/*compilerCache:
function cache( key, value ) {
// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
if ( keys.push( key += " " ) > Expr.cacheLength ) {
// Only keep the most recent entries
delete cache[ keys.shift() ];
}
return (cache[ key ] = value);
}
*/
hasDuplicate = false,
sortOrder = function( a, b ) {
if ( a === b ) {
hasDuplicate = true;
return 0;
}
return 0;
}, // General-purpose constants
strundefined = typeof undefined,
MAX_NEGATIVE = 1 << 31, // Instance methods
hasOwn = ({}).hasOwnProperty,
arr = [],
pop = arr.pop,
push_native = arr.push,
push = arr.push,
slice = arr.slice,
// Use a stripped-down indexOf if we can't use a native one
indexOf = arr.indexOf || function( elem ) {
var i = 0,
len = this.length;
for ( ; i < len; i++ ) {
if ( this[i] === elem ) {
return i;
}
}
return -1;
}, booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", // Regular expressions // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
//匹配空白 水平制表符 回车 换行 换页
whitespace = "[\\x20\\t\\r\\n\\f]",
// http://www.w3.org/TR/css3-syntax/#characters
//可以匹配 由\\. 或 单词字符(所有字母数字下划线) 或 汉字(包括汉字标点符号),这里也可以说是全角符号组成
characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", // Loosely modeled on CSS identifier characters
// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
//识别码
identifier = characterEncoding.replace( "w", "w#" ), // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
//attributes ="\[[\x20\t\r\n\f]*((?:\\.|[\w-]|[^\x00-\xa0])+)[\x20\t\r\n\f]*(?:([*^$|!~]?=)[\x20\t\r\n\f]*(?:(['"])((?:\\.|[^\\])*?)\3|((?:\\.|[\w#-]|[^\x00-\xa0])+)|)|)[\x20\t\r\n\f]*\]"
//匹配属性 例如:[a="b"] [a=b] [a|='er']
attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
"*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", // Prefer arguments quoted,
// then not containing pseudos/brackets,
// then attribute selectors/non-parenthetical expressions,
// then anything else
// These preferences are here to reduce the number of selectors
// needing tokenize in the PSEUDO preFilter
pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)", // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
//匹配开始或结束的空白字符
rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
//匹配逗号
rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
//匹配组合器 包括> + ~ 及"[\\x20\\t\\r\\n\\f]"
rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
//兄弟节点?
rsibling = new RegExp( whitespace + "*[+~]" ),
//属性选择器的等号后边部分,如:=aa]
rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*)" + whitespace + "*\\]", "g" ),
//rpseudo=/:((?:\\.|[\w-]|[^\x00-\xa0])+)(?:\(((['"])((?:\\.|[^\\])*?)\3|((?:\\.|[^\\()[\]]|\[[\x20\t\r\n\f]*((?:\\.|[\w-]|[^\x00-\xa0])+)[\x20\t\r\n\f]*(?:([*^$|!~]?=)[\x20\t\r\n\f]*(?:(['"])((?:\\.|[^\\])*?)\8|((?:\\.|[\w#-]|[^\x00-\xa0])+)|)|)[\x20\t\r\n\f]*\])*)|.*)\)|)/
//伪类选择器 如::nth-child(3)
rpseudo = new RegExp( pseudos ),
//匹配识别码
ridentifier = new RegExp( "^" + identifier + "$" ), matchExpr = {//匹配各种选择器的正则表达式
"ID": new RegExp( "^#(" + characterEncoding + ")" ),//ID选择器
"CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),//类
"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
"ATTR": new RegExp( "^" + attributes ),
"PSEUDO": new RegExp( "^" + pseudos ),
"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
// For use in libraries implementing .is()
// We use this for POS matching in `select`
"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
},
//检查是否原生代码
rnative = /^[^{]+\{\s*\[native \w/, // Easily-parseable/retrievable ID or TAG or CLASS selectors
rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
//匹配input元素,其实包含了四种:input|select|textarea|button
rinputs = /^(?:input|select|textarea|button)$/i,
rheader = /^h\d$/i, rescape = /'|\\/g, // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
//匹配解码字符
runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
funescape = function( _, escaped, escapedWhitespace ) {//_代表整个匹配项,escaped代表第一个匹配项,escapedWhitespace代表第二个分组匹配项,即空白匹配项
var high = "0x" + escaped - 0x10000;
// NaN means non-codepoint
// Support: Firefox
// Workaround erroneous numeric interpretation of +"0x"
return high !== high || escapedWhitespace ?
escaped :
// BMP codepoint
high < 0 ?
String.fromCharCode( high + 0x10000 ) :
// Supplemental Plane codepoint (surrogate pair)
String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
};
接下来就是一些功能函数,下边这张图说明了其中的功能函数的作用:

sizzle源码分析 (1)sizzle架构

 
最后把sizzle和jquery关联起来:
jQuery.find = Sizzle;
jQuery.expr = Sizzle.selectors;
jQuery.expr[":"] = jQuery.expr.pseudos;
jQuery.unique = Sizzle.uniqueSort;
jQuery.text = Sizzle.getText;
jQuery.isXMLDoc = Sizzle.isXML;
jQuery.contains = Sizzle.contains;